diff --git a/AutoEvent-NWApi/Interfaces/Event.cs b/AutoEvent-NWApi/Interfaces/Event.cs deleted file mode 100644 index 807b4443..00000000 --- a/AutoEvent-NWApi/Interfaces/Event.cs +++ /dev/null @@ -1,898 +0,0 @@ -using AutoEvent.API.Attributes; -using PluginAPI.Core; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using AutoEvent.API; -using AutoEvent.API.Enums; -using AutoEvent.Configs; -using HarmonyLib; -using MEC; -using UnityEngine; -using YamlDotNet.Core; - -namespace AutoEvent.Interfaces -{ - public abstract class Event : IEvent - { -#region Static Implementations // Static tools for registering and viewing events. - /// - /// A list of all registered events including external events and events. - /// - public static List Events { get; set; } = new List(); - - - /// - /// Registers all of the Events. - /// - internal static void RegisterInternalEvents() - { - Assembly callingAssembly = Assembly.GetCallingAssembly(); - Type[] types = callingAssembly.GetTypes(); - - foreach (Type type in types) - { - try - { - if (type.IsAbstract || - type.IsEnum || - type.IsInterface || type.GetInterfaces().All(x => x != typeof(IEvent))) - continue; - - object evBase = Activator.CreateInstance(type); - if(evBase is null || evBase is not Event ev || - type.GetCustomAttributes(typeof(DisabledFeaturesAttribute), false).Any(x => x is not null)) - continue; - - if (!ev.AutoLoad) - continue; - ev.Id = Events.Count; - try - { - ev.VerifyEventInfo(); - ev.LoadConfigs(); - ev.LoadTranslation(); - ev.InstantiateEvent(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"[EventLoader] {ev.Name} encountered an error while registering.", LogLevel.Warn, true); - DebugLogger.LogDebug($"[EventLoader] {e}", LogLevel.Debug); - } - string confs = ""; - foreach (var conf in ev.ConfigPresets) - { - confs += $"{conf.PresetName}, "; - } - Events.Add(ev); - DebugLogger.LogDebug($"[EventLoader] {ev.Name} has been registered. Presets: {(confs + ",").Replace(", ,", "")}", LogLevel.Info, true); - } - catch (MissingMethodException) { } - catch (Exception ex) - { - DebugLogger.LogDebug($"[EventLoader] cannot register an event.", LogLevel.Error, true); - DebugLogger.LogDebug($"{ex}", LogLevel.Debug); - - } - } - } - - /// - /// Gets an event by it's name. - /// - /// The name of the event to search for. - /// The first event found with the same name (Case-Insensitive). - public static Event GetEvent(string type) - { - Event ev = null; - - if (int.TryParse(type, out int id)) - return GetEvent(id); - - if (!TryGetEventByCName(type, out ev)) - return Events.FirstOrDefault(ev => ev.Name.ToLower() == type.ToLower()); - - return ev; - } - - /// - /// Gets an event by it's ID. - /// - /// The ID of the event to search for. - /// The first event found with the same ID. - public static Event GetEvent(int id) => Events.FirstOrDefault(x => x.Id == id); - - private static bool TryGetEventByCName(string type, out Event ev) - { - return (ev = Events.FirstOrDefault(x => x.CommandName == type)) != null; - } -#endregion -#region Abstract Implementations // Tools that have been abstracted into the event class. - #region Event Information // Information that event authors can specify about the event. - /// - /// The name of the event. - /// - public abstract string Name { get; set; } - - /// - /// The Id of the event. It is set by AutoEvent. - /// - public int Id { get; internal set; } - - /// - /// A description of the event. - /// - public abstract string Description { get; set; } - - /// - /// The name of the author of the event. - /// - public abstract string Author { get; set; } - - /// - /// The name of the map that is used to run the map via command. - /// - public abstract string CommandName { get; set; } - #endregion - #region Event Settings // Settings that event authors can define to modify the abstracted implementations - /// - /// How long to wait after the round finishes, before the cleanup begins. Default is 10 seconds. - /// - protected virtual float PostRoundDelay { get; set; } = 10f; - - /// - /// Obsolete. Use instead. - /// - [Obsolete("This is no longer supported. Inherit IExiledEvent instead.")] - public virtual bool UsesExiled { get; protected set; } = false; - - /// - /// If using NwApi or Exiled as the base plugin, set this to false, and manually add your plugin to Event.Events (List[Events]). - /// This prevents double-loading your plugin assembly. - /// - public virtual bool AutoLoad { get; protected set; } = true; - - /// - /// Used to safely kill the while loop, without have to forcible kill the coroutine. - /// - protected virtual bool KillLoop { get; set; } = false; - - /// - /// How many seconds the event waits after each ProcessFrame(). - /// - protected virtual float FrameDelayInSeconds { get; set; } = 1f; - - /// - /// Use this to force specific settings for friendly fire. - /// - protected virtual FriendlyFireSettings ForceEnableFriendlyFire { get; set; } = FriendlyFireSettings.Default; - - /// - /// Use this to force specific settings for friendly fire autoban. - /// - protected virtual FriendlyFireSettings ForceEnableFriendlyFireAutoban { get; set; } = FriendlyFireSettings.Default; - - #endregion - #region Event Variables // Variables that the event author has access too, which are abstracted into the event system. - - - /// - /// The coroutine handle of the main event thread which calls ProcessFrame(). - /// - protected virtual CoroutineHandle GameCoroutine { get; set; } - - /// - /// The coroutine handle for the start countdown broadcast. - /// - protected virtual CoroutineHandle BroadcastCoroutine { get; set; } - - // ReSharper disable once UnusedAutoPropertyAccessor.Global - /// - /// The DateTime (UTC) that the plugin started at. - /// - public virtual DateTime StartTime { get; protected set; } - - /// - /// The elapsed time since the plugin started. - /// - public virtual TimeSpan EventTime { get; protected set; } - - #endregion - #region Event API Methods // Methods that can be used as api calls such as starting music / spawning map. - /// - /// Starts the defined Audio. Can be used to trigger a late audio cue. SoundInfo.StartAutomatically - /// - /// Should the audio abide by - protected void StartAudio(bool checkIfAutomatic = false) - { - DebugLogger.LogDebug($"Starting Audio: " + - $"{(this is IEventSound s ? "true, " + - $"{(!string.IsNullOrEmpty(s.SoundInfo.SoundName)? "true" : "false")}, " + - $"{(!checkIfAutomatic ? "true" : "false")}, " + - $"{(s.SoundInfo.StartAutomatically ? "true" : "false")}" : "false")}", - LogLevel.Debug); - if (this is IEventSound sound && !string.IsNullOrEmpty(sound.SoundInfo.SoundName) && - (!checkIfAutomatic || sound.SoundInfo.StartAutomatically)) - { - // play sound - Extensions.PlayAudio( - sound.SoundInfo.SoundName, - sound.SoundInfo.Volume, - sound.SoundInfo.Loop, - Name); - } - } - - /// - /// Can be used to stop the running audio. - /// - protected void StopAudio() - { - DebugLogger.LogDebug("Stopping Audio", LogLevel.Debug); - Extensions.StopAudio(); - } - - /// - /// Spawns the defined Map. Can be used to trigger a late Map spawn. MapInfo.SpawnAutomatically - /// - /// Should the audio abide by - - protected void SpawnMap(bool checkIfAutomatic = false) - { - DebugLogger.LogDebug($"Spawning Map: " + - $"{(this is IEventMap m ? "true, " + - $"{(!string.IsNullOrEmpty(m.MapInfo.MapName)? "true" : "false")}, " + - $"{(!checkIfAutomatic ? "true" : "false")}, " + - $"{(m.MapInfo.SpawnAutomatically ? "true" : "false")}" : "false")}", - LogLevel.Debug); - if (this is IEventMap map && !string.IsNullOrEmpty(map.MapInfo.MapName) && - (!checkIfAutomatic || map.MapInfo.SpawnAutomatically)) - { - // load map - map.MapInfo.Map = Extensions.LoadMap( - map.MapInfo.MapName, - map.MapInfo.Position, - map.MapInfo.MapRotation, - map.MapInfo.Scale); - } - } - - /// - /// Can be used to de-spawn the map. - /// - protected void DeSpawnMap() - { - DebugLogger.LogDebug($"DeSpawning Map. {this is IEventMap}", LogLevel.Debug); - if (this is IEventMap eventMap) - { - Extensions.UnLoadMap(eventMap.MapInfo.Map); - } - } - - /// - /// Can be used to get a list of each defined in the plugin. - /// - /// Returns a list of the current values of each - public List GetCurrentConfigsValues() - { - List eventConfigs = new List(); - foreach (PropertyInfo propertyInfo in this.GetType().GetProperties()) - { - var attr = propertyInfo.GetCustomAttribute(); - if (attr is null) - continue; - object value = propertyInfo.GetValue(this); - if(value is not EventConfig conf) - continue; - eventConfigs.Add(conf); - } - - return eventConfigs; - } - - /// - /// Used to start the event safely. - /// - public void StartEvent() - { - DebugLogger.LogDebug($"Starting Event {Name}", LogLevel.Debug); - OnInternalStart(); - } - - /// - /// Used to stop the event safely. - /// - public void StopEvent() - { - DebugLogger.LogDebug($"Stopping Event {Name}", LogLevel.Debug); - OnInternalStop(); - } - - #endregion - #region Event Methods // Methods that event authors can / must utilize that are abstracted into the event system. - /// - /// Base constructor for an event. - /// - public Event(){ } - - /// - /// The method that is called when the event is registered. Should be used instead of a constructor to prevent type load exceptions. - /// - public virtual void InstantiateEvent() { } - - /// - /// Called when the event is started. - /// - protected abstract void OnStart(); - - /// - /// Used to register events for plugins. - /// - protected virtual void RegisterEvents() { } - - /// - /// Called after start in a coroutine. Can be used as a countdown coroutine. - /// - protected virtual IEnumerator BroadcastStartCountdown() - { - yield break; - } - - /// - /// Called after is finished. Can be used to remove walls, or give players items. - /// - protected virtual void CountdownFinished() { } - - /// - /// Used to determine whether the event should end or not. - /// - /// True if the round is finished. False if the round should continue running. - protected abstract bool IsRoundDone(); - - /// - /// Called once a second. - /// - protected virtual void ProcessFrame() { } - - /// - /// Called when the event is finished. If the event is stopped via , this won't be called, as the event never truly finishes properly. - /// - protected abstract void OnFinished(); - - /// - /// Called if the event is forcibly stopped. If this is called, won't be called. - /// - protected virtual void OnStop() { } - - /// - /// Used to unregister events for plugins. - /// - protected virtual void UnregisterEvents() { } - - /// - /// The overridable class for after and event is finished / stopped and cleanup is occuring. - /// - protected virtual void OnCleanup() { } - #endregion - #region Internal Event Methods // Methods that are for the internal use by the event system to call or modify other abstracted properties or methods. - - private string CreateConfigFolder() - { - string path = Path.Combine(AutoEvent.Singleton.Config.EventConfigsDirectoryPath, this.Name); - AutoEvent.CreateDirectoryIfNotExists(path); - AutoEvent.CreateDirectoryIfNotExists(Path.Combine(path, "Presets")); - return path; - } - - /// - /// A list of available config presets. WIP - /// - public List ConfigPresets { get; set; } = new List(); - - private List _confTypes { get; set; } = new List(); - - /// - /// Ensures that information such as the command name is valid. - /// - internal void VerifyEventInfo() - { - this.CommandName = CommandName.ToCamelCase(true); - } - - /// - /// Validates and loads any configs and presets for the given event. - /// - internal void LoadConfigs() - { - if (this.ConfigPresets is not null) - this.ConfigPresets.Clear(); - else - this.ConfigPresets = new List(); - - int loadedConfigs = 0; - var path = CreateConfigFolder(); - try - { - loadedConfigs = _loadValidConfigs(path); - } - catch (Exception e) - { - DebugLogger.LogDebug($"[EventLoader] LoadConfigs()->_loadValidConfigs(path) has caught an exception while loading configs for the plugin {Name}", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - try - { - _createPresets(Path.Combine(path, "Presets")); - } - catch (Exception e) - { - DebugLogger.LogDebug($"[EventLoader] LoadConfigs()->_createPresets(path) has caught an exception while loading configs for the plugin {Name}", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - try - { - _loadPresets(Path.Combine(path, "Presets")); - } - catch (Exception e) - { - DebugLogger.LogDebug($"[EventLoader] LoadConfigs()->_loadPresets(path) has caught an exception while loading configs for the plugin {Name}", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - // DebugLogger.LogDebug($"[EventLoader] Loaded {loadedConfigs} Configs, and {ConfigPresets.Count} Config Presets, for plugin {Name}", LogLevel.Info); - } - - /// - /// Loads any configs. - /// - /// The base event path. - private int _loadValidConfigs(string path) - { - int i = 0; - foreach (var property in this.GetType().GetProperties()) - { - var conf = property.GetCustomAttribute(); - if (conf is EventConfigPresetAttribute) - { - continue; - } - if (conf is null) - { - continue; - } - - DebugLogger.LogDebug($"Config \"{property.Name}\" found for {Name}", LogLevel.Debug); - object config = conf.Load(path, property.Name, property.PropertyType); - if (config is not EventConfig evConfig) - { - DebugLogger.LogDebug($"Config was found that does not inherit Event Config. It will be skipped.", LogLevel.Warn, true); - DebugLogger.LogDebug($"(Event {this.Name}) Config: {property.Name}.", LogLevel.Debug); - continue; - } - - if (ConfigPresets.Count > 0) - evConfig.PresetName = $"Default-{ConfigPresets.Count - 1}"; - else - evConfig.PresetName = "Default"; - _setRandomMap(evConfig); - _setRandomSound(evConfig); - - property.SetValue(this, config); - ConfigPresets.Add((EventConfig)config); - _confTypes.Add(config.GetType()); - - i++; - } - - return i; - } - - /// - /// Assigns a random map. - /// - /// - private void _setRandomMap(EventConfig conf) - { - if (this is IEventMap map && conf.AvailableMaps is not null && conf.AvailableMaps.Count > 0) - { - bool spawnAutomatically = map.MapInfo.SpawnAutomatically; - if (conf.AvailableMaps.Count == 1) - { - map.MapInfo = conf.AvailableMaps[0].Map; - map.MapInfo.SpawnAutomatically = spawnAutomatically; - goto Message; - } - - foreach (var mapItem in conf.AvailableMaps.Where(x => x.Chance <= 0)) - mapItem.Chance = 1; - - float totalChance = conf.AvailableMaps.Sum(x => x.Chance); - - for (int i = 0; i < conf.AvailableMaps.Count - 1; i++) - { - if (UnityEngine.Random.Range(0, totalChance) <= conf.AvailableMaps[i].Chance) - { - map.MapInfo = conf.AvailableMaps[i].Map; - map.MapInfo.SpawnAutomatically = spawnAutomatically; - goto Message; - } - } - map.MapInfo = conf.AvailableMaps[conf.AvailableMaps.Count - 1].Map; - map.MapInfo.SpawnAutomatically = spawnAutomatically; - Message: - DebugLogger.LogDebug($"[{this.Name}] Map {map.MapInfo.MapName} selected.", LogLevel.Debug); - } - - } - /// - /// Assigns a random sound. - /// - /// - private void _setRandomSound(EventConfig conf) - { - if (this is IEventSound sound && conf.AvailableSounds is not null && conf.AvailableSounds.Count > 0) - { - bool startAutomatically = sound.SoundInfo.StartAutomatically; - if (conf.AvailableSounds.Count == 1) - { - sound.SoundInfo = conf.AvailableSounds[0].Sound; - sound.SoundInfo.StartAutomatically = startAutomatically; - goto Message; - } - - foreach (var soundItem in conf.AvailableSounds.Where(x => x.Chance <= 0)) - soundItem.Chance = 1; - - float totalChance = conf.AvailableSounds.Sum(x => x.Chance); - - for (int i = 0; i < conf.AvailableSounds.Count - 1; i++) - { - if (UnityEngine.Random.Range(0, totalChance) <= conf.AvailableSounds[i].Chance) - { - sound.SoundInfo = conf.AvailableSounds[i].Sound; - sound.SoundInfo.StartAutomatically = startAutomatically; - goto Message; - } - } - sound.SoundInfo = conf.AvailableSounds[conf.AvailableSounds.Count - 1].Sound; - sound.SoundInfo.StartAutomatically = startAutomatically; - Message: - DebugLogger.LogDebug($"[{this.Name}] Sound {sound.SoundInfo.SoundName} selected.", LogLevel.Debug); - } - } - /// - /// Creates a preset.yml file for each preset found. - /// - /// The base event path. - private void _createPresets(string path) - { - foreach (var property in this.GetType().GetProperties()) - { - var conf = property.GetCustomAttribute(); - if (conf is null || conf.IsLoaded) - { - continue; - } - // DebugLogger.LogDebug($"Embedded Config Preset \"{property.Name}\" found for {Name}", LogLevel.Debug); - - conf.Load(path, property, property.GetValue(this)); - } - } - - /// - /// Loads all config presets to the preset List. - /// - /// The base event path. - private void _loadPresets(string path) - { - foreach (string file in Directory.GetFiles(path, "*.yml")) - { - string fileName = Path.GetFileNameWithoutExtension(file); - - object conf = Configs.Serialization.Deserializer.Deserialize(File.ReadAllText(file), _confTypes.FirstOrDefault() ?? typeof(EventConfig)); - if (conf is not EventConfig) - { - DebugLogger.LogDebug("Not Event Config."); - continue; - } - // DebugLogger.LogDebug($"Config Preset \"{file}\" loaded for {Name}", LogLevel.Debug); - ((EventConfig)conf).PresetName = fileName; - ConfigPresets.Add((EventConfig)conf); - DebugLogger.LogDebug($"Config Preset: {conf.GetType().Name}, BaseType: {conf.GetType().BaseType?.Name}"); - } - } - - /// - /// Loads any translations present - /// - internal void LoadTranslation() - { - /*if (this is ITranslation) - { - - }*/ - } - /// - /// Triggers internal actions to stop an event. - /// - private void OnInternalStop() - { - KillLoop = true; - Timing.KillCoroutines(new CoroutineHandle[] { BroadcastCoroutine }); - Timing.CallDelayed(FrameDelayInSeconds + .1f, () => - { - if (GameCoroutine.IsRunning) - { - Timing.KillCoroutines(new CoroutineHandle[] { GameCoroutine }); - } - OnInternalCleanup(); - }); - - try - { - OnStop(); - } - catch (Exception e) - { - - DebugLogger.LogDebug($"Caught an exception at Event.OnStop().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - EventStopped?.Invoke(Name); - - } - /// - /// Used to trigger plugin events in the right order. - /// - private void OnInternalStart() - { - KillLoop = false; - _cleanupRun = false; - AutoEvent.ActiveEvent = this; - EventTime = new TimeSpan(); - StartTime = DateTime.UtcNow; - - try - { - // todo finish implementation. - if (this.ForceEnableFriendlyFire == FriendlyFireSettings.Enable) - { - FriendlyFireSystem.EnableFriendlyFire(this.ForceEnableFriendlyFireAutoban == FriendlyFireSettings.Enable); - return; - } - - if (this.ForceEnableFriendlyFire == FriendlyFireSettings.Disable) - { - FriendlyFireSystem.DisableFriendlyFire(); - return; - } - - if (this.ForceEnableFriendlyFireAutoban == FriendlyFireSettings.Enable) - { - FriendlyFireSystem.EnableFriendlyFireDetector(); - return; - } - - if (this.ForceEnableFriendlyFireAutoban == FriendlyFireSettings.Disable) - { - FriendlyFireSystem.DisableFriendlyFireDetector(); - } - } - catch (Exception e) - { - DebugLogger.LogDebug($"Could not modify friendly fire / ff autoban settings.", LogLevel.Error, true); - DebugLogger.LogDebug($"{e}"); - } - - SpawnMap(true); - try - { - RegisterEvents(); - } - catch (Exception e) - { - - DebugLogger.LogDebug($"Caught an exception at Event.RegisterEvents().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - - } - - try - { - OnStart(); - } - catch (Exception e) - { - - DebugLogger.LogDebug($"Caught an exception at Event.OnStart().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - EventStarted?.Invoke(Name); - StartAudio(true); - Timing.RunCoroutine(RunTimingCoroutine(), "TimingCoroutine"); - } - - /// - /// Used to prevent blocking the main game thread while triggering other coroutines. - /// - /// - private IEnumerator RunTimingCoroutine() - { - BroadcastCoroutine = Timing.RunCoroutine(BroadcastStartCountdown(), "Broadcast Coroutine"); - yield return Timing.WaitUntilDone(BroadcastCoroutine); - if (KillLoop) - { - yield break; - } - try - { - CountdownFinished(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event.CountdownFinished().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - GameCoroutine = Timing.RunCoroutine(RunGameCoroutine(), "Event Coroutine"); - yield return Timing.WaitUntilDone(GameCoroutine); - if (KillLoop) - { - yield break; - } - try - { - OnFinished(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event.OnFinished().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - var handle = Timing.CallDelayed(PostRoundDelay, () => - { - if (!_cleanupRun) - { - OnInternalCleanup(); - } - }); - yield return Timing.WaitUntilDone(handle); - } - - /// - /// The coroutine that is called for processing frames. We recommend avoiding overrides to this, since this may mess with other logic. - /// - /// - protected virtual IEnumerator RunGameCoroutine() - { - while (!IsRoundDone() || DebugLogger.AntiEnd) - { - if (KillLoop) - { - yield break; - } - try - { - ProcessFrame(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event.ProcessFrame().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - EventTime += TimeSpan.FromSeconds(FrameDelayInSeconds); - yield return Timing.WaitForSeconds(this.FrameDelayInSeconds); - } - yield break; - } - - /// - /// Used to prevent double cleanups. - /// - private bool _cleanupRun = false; - - /// - /// The internal method used to trigger cleanup for maps, ragdolls, items, sounds, and teleporting players to the spawn room. - /// - private void OnInternalCleanup() - { - _cleanupRun = true; - try - { - UnregisterEvents(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event.OnUnregisterEvents().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - try - { - FriendlyFireSystem.RestoreFriendlyFire(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Friendly Fire was not able to be restored. Please ensure it is disabled. PLAYERS MAY BE AUTO-BANNED ACCIDENTALLY OR MAY NOT BE BANNED FOR FF.", LogLevel.Error, true); - DebugLogger.LogDebug($"{e}"); - } - - try - { - DeSpawnMap(); - StopAudio(); - Extensions.CleanUpAll(); - Extensions.TeleportEnd(); - - } - catch (Exception e) - { - DebugLogger.LogDebug("Caught an exception at Event.OnInternalCleanup().GeneralCleanup().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - try - { - OnCleanup(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event.OnCleanup().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - // StartTime = null; - // EventTime = null; - try - { - CleanupFinished?.Invoke(Name); - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event.CleanupFinished.Invoke().", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - AutoEvent.ActiveEvent = null; - try - { - EventConfig conf = this.GetCurrentConfigsValues().FirstOrDefault(); - if (conf is not null) - { - this._setRandomMap(conf); - this._setRandomSound(conf); - } - } - catch (Exception e) - { - DebugLogger.LogDebug($"Caught an exception at Event._setMap.", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}", LogLevel.Debug); - } - - } - #endregion - #region Event Events // These events are triggered internally and can be used by an event manager to detect when certain stages are complete. - public delegate void EventStoppedHandler(string eventName); - public delegate void CleanupFinishedHandler(string eventName); - public delegate void EventStartedHandler(string eventName); - - /// - /// Called when the event start is triggered. - /// - public virtual event EventStartedHandler EventStarted; - - /// - /// Called when the event cleanup is finished. The event is completely finished and disposed of once this is called. - /// - public virtual event CleanupFinishedHandler CleanupFinished; - - /// - /// Called when the event is stopped. When the event is stopped, OnFinished() won't be called, but OnCleanup() will be called. - /// - public virtual event EventStoppedHandler EventStopped; - #endregion -#endregion - } -} diff --git a/AutoEvent-NWApi/Loader.cs b/AutoEvent-NWApi/Loader.cs deleted file mode 100644 index 2f5ec0f7..00000000 --- a/AutoEvent-NWApi/Loader.cs +++ /dev/null @@ -1,398 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using AutoEvent.Interfaces; -using PluginAPI.Helpers; -using PluginAPI.Core; - -namespace AutoEvent; - -public class Loader -{ - /// - /// Overrides the Exiled check for the version of the plugin that is exiled exclusive. - /// -#if EXILED - private const bool IsExiledPlugin = true; -#else - private const bool IsExiledPlugin = false; -#endif - /// - /// If enabled, a debug log is output everytime a plugin is loaded. Not necessary for players. - /// - private const bool LogAllPluginsOnRegister = false; - - /// - /// Debug logging only - /// - private static bool Debug => AutoEvent.Debug; - - /// - /// Checks to see if exiled is present on this server. - /// - /// - private static bool isExiledPresent() - { - if (IsExiledPlugin) - { - return true; - } - foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) - { - if (ass.GetName().Name == "Exiled.Loader") - { - return true; - } - } - return false; - - } - /// - /// Gets plugin dependencies. - /// - public static List Dependencies { get; } = new(); - - /// - /// A list of additional events found. - /// - public static List Events = new List(); - - /// - /// Loads all plugins. - /// - public static void LoadEvents() - { - Dictionary locations = new Dictionary(); -#if !EXILED - string filepath = AutoEvent.Singleton.Config.ExternalEventsDirectoryPath; -#else - string filepath = Path.Combine(AutoEvent.BaseConfigPath, "Events"); -#endif - foreach (string assemblyPath in Directory.GetFiles(filepath, "*.dll")) - { - try - { - - Assembly assembly = LoadAssembly(assemblyPath); - - if (assembly is null) - continue; - - locations[assembly] = assemblyPath; - } - catch (TargetInvocationException e) - { - - DebugLogger.LogDebug("[ExternalEventLoader] Could not load a plugin. Check to make sure it does not require exiled or that you have exiled installed.", LogLevel.Warn, true); - DebugLogger.LogDebug(e.ToString(),LogLevel.Debug); - } - catch (Exception e) - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Could not load a plugin due to an error.", LogLevel.Warn, true); - DebugLogger.LogDebug(e.ToString(),LogLevel.Debug); - } - } - - foreach (Assembly assembly in locations.Keys) - { - if (locations[assembly].Contains("dependencies")) - continue; - try - { - - List eventList = CreateEventPlugin(assembly); - foreach (Event eventPlugin in eventList) - { - try - { - - if (eventPlugin is null) - continue; - - if (!eventPlugin.AutoLoad) - { - continue; - } - AssemblyInformationalVersionAttribute attribute = - assembly.GetCustomAttribute(); - - DebugLogger.LogDebug($"[ExternalEventLoader] Loaded Event {eventPlugin.Name} by {(eventPlugin.Author is not null ? $"{eventPlugin.Author}" : attribute is not null ? attribute.InformationalVersion : string.Empty)}", LogLevel.Info, LogAllPluginsOnRegister); - - try - { - eventPlugin.VerifyEventInfo(); - eventPlugin.LoadConfigs(); - eventPlugin.LoadTranslation(); - eventPlugin.InstantiateEvent(); - } - catch (Exception e) - { - DebugLogger.LogDebug($"[EventLoader] {eventPlugin.Name} encountered an error while registering.",LogLevel.Warn, true); - DebugLogger.LogDebug(e.ToString(),LogLevel.Debug); - } - Events.Add(eventPlugin); - } - catch (Exception) - { - //unused - } - } - } - catch (Exception) - { - // unused - } - } - } - - /// - /// Loads an assembly. - /// - /// The path to load the assembly from. - /// Returns the loaded assembly or . - public static Assembly LoadAssembly(string path) - { - try - { - Assembly assembly = Assembly.Load(File.ReadAllBytes(path)); - - ResolveAssemblyEmbeddedResources(assembly); - - return assembly; - } - catch (Exception exception) - { - DebugLogger.LogDebug($"[ExternalEventLoader] Error while loading an assembly at {path}! {exception}", LogLevel.Warn); - } - - return null; - } - - /// - /// Create a plugin instance. - /// - /// The event assembly. - /// Returns the created plugin instance or . - public static List CreateEventPlugin(Assembly assembly) - { - List eventsFound = new List(); - try - { - foreach (Type type in assembly.GetTypes()) - { - try - { - if (type.IsAbstract || type.IsInterface) - { - DebugLogger.LogDebug( - $"[ExternalEventLoader] \"{type.FullName}\" is an interface or abstract class, skipping.", - LogLevel.Debug); - - continue; - } - - if (!IsDerivedFromPlugin(type)) - { - DebugLogger.LogDebug( - $"[ExternalEventLoader] \"{type.FullName}\" does not inherit from Event, skipping.", - LogLevel.Debug); - - continue; - } - - if(type.GetInterface(nameof(IExiledEvent)) is not null && !isExiledPresent()) - { - DebugLogger.LogDebug($"[ExternalEventLoader] Cannot register plugin {type.Name} because it requires exiled to work. Exiled has not loaded yet, or is not present at all.",LogLevel.Warn, true); - continue; - } - - DebugLogger.LogDebug($"[ExternalEventLoader] Loading type {type.FullName}", LogLevel.Debug); - - Event plugin = null; - - ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); - if (constructor is not null) - { - - DebugLogger.LogDebug("[ExternalEventLoader] Public default constructor found, creating instance...", LogLevel.Debug); - - plugin = constructor.Invoke(null) as Event; - } - else - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Constructor wasn't found, searching for a property with the {type.FullName} type...", LogLevel.Debug); - - - object value = Array - .Find( - type.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public), - property => property.PropertyType == type)?.GetValue(null); - - if (value is not null) - plugin = value as Event; - } - - if (plugin is null) - { - DebugLogger.LogDebug($"[ExternalEventLoader] {type.FullName} is a valid event, but it cannot be instantiated! It either doesn't have a public default constructor without any arguments or a static property of the {type.FullName} type!", LogLevel.Error, true); - continue; - } - - DebugLogger.LogDebug($"[ExternalEventLoader] Instantiated type {type.FullName}", LogLevel.Debug); - - eventsFound.Add(plugin); - } - catch (ReflectionTypeLoadException reflectionTypeLoadException) - { - DebugLogger.LogDebug("[ExternalEventLoader] An external event has failed to load! Ensure that you have Exiled installed, or that all of the plugins don't require Exiled.", LogLevel.Warn, true); - DebugLogger.LogDebug($"[ExternalEventLoader] Error while initializing event {assembly.GetName().Name} (at {assembly.Location})! {reflectionTypeLoadException}", LogLevel.Debug); - - foreach (Exception loaderException in reflectionTypeLoadException.LoaderExceptions) - { - DebugLogger.LogDebug($"[ExternalEventLoader] {loaderException}", LogLevel.Warn); - } - } - catch (Exception exception) - { - DebugLogger.LogDebug("[ExternalEventLoader] An external event has failed to load! Ensure that you have Exiled installed, or that all of the plugins don't require Exiled.", LogLevel.Warn, true); - DebugLogger.LogDebug($"[ExternalEventLoader] Error while initializing plugin {assembly.GetName().Name} (at {assembly.Location})! {exception}", LogLevel.Debug); - } - } - return eventsFound; - } - catch (ReflectionTypeLoadException reflectionTypeLoadException) - { - DebugLogger.LogDebug("[ExternalEventLoader] An external event has failed to load! Ensure that you have Exiled installed, or that all of the plugins don't require Exiled.", LogLevel.Warn, true); - DebugLogger.LogDebug($"[ExternalEventLoader] Error while initializing event {assembly.GetName().Name} (at {assembly.Location})! {reflectionTypeLoadException}", LogLevel.Debug); - - - - foreach (Exception loaderException in reflectionTypeLoadException.LoaderExceptions) - { - DebugLogger.LogDebug($"[ExternalEventLoader] {loaderException}", LogLevel.Error); - } - } - catch (Exception exception) - { - DebugLogger.LogDebug("[ExternalEventLoader] An external event has failed to load! Ensure that you have Exiled installed, or that all of the plugins don't require Exiled.", LogLevel.Warn, true); - DebugLogger.LogDebug($"[ExternalEventLoader] Error while initializing plugin {assembly.GetName().Name} (at {assembly.Location})! {exception}", LogLevel.Error); - - } - - return eventsFound; - } - - /// - /// Indicates that the passed type is derived from the plugin type. - /// - /// Type. - /// if passed type is derived from , otherwise . - private static bool IsDerivedFromPlugin(Type type) - { - while (type is not null) - { - type = type.BaseType; - - if (type == typeof(Event)) - return true; - - if (type is { IsGenericType: true }) - { - Type genericTypeDef = type.GetGenericTypeDefinition(); - DebugLogger.LogDebug($"[ExternalEventLoader] Generic type {genericTypeDef}", LogLevel.Debug); - - - if (genericTypeDef == typeof(Event)) - return true; - } - else - { - DebugLogger.LogDebug($"[ExternalEventLoader] Not Generic Type {type?.Name}.", LogLevel.Debug); - } - } - - return false; - } - - /// - /// Attempts to load Embedded (compressed) assemblies from specified Assembly. - /// - /// Assembly to check for embedded assemblies. - private static void ResolveAssemblyEmbeddedResources(Assembly target) - { - try - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Attempting to load embedded resources for {target.FullName}", LogLevel.Debug); - - - string[] resourceNames = target.GetManifestResourceNames(); - - foreach (string name in resourceNames) - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Found resource {name}", LogLevel.Debug); - - - if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) - { - using MemoryStream stream = new(); - - - DebugLogger.LogDebug($"[ExternalEventLoader] Loading resource {name}", LogLevel.Debug); - - - Stream dataStream = target.GetManifestResourceStream(name); - - if (dataStream == null) - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Unable to resolve resource {name} Stream was null", LogLevel.Error, true); - continue; - } - - dataStream.CopyTo(stream); - - Dependencies.Add(Assembly.Load(stream.ToArray())); - - - - DebugLogger.LogDebug($"[ExternalEventLoader] Loaded resource {name}", LogLevel.Debug); - } - else if (name.EndsWith(".dll.compressed", StringComparison.OrdinalIgnoreCase)) - { - Stream dataStream = target.GetManifestResourceStream(name); - - if (dataStream == null) - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Unable to resolve resource {name} Stream was null", LogLevel.Error, true); - continue; - } - - using DeflateStream stream = new(dataStream, CompressionMode.Decompress); - using MemoryStream memStream = new(); - - - DebugLogger.LogDebug($"[ExternalEventLoader] Loading resource {name}", LogLevel.Debug); - - stream.CopyTo(memStream); - - Dependencies.Add(Assembly.Load(memStream.ToArray())); - - - DebugLogger.LogDebug($"[ExternalEventLoader] Loaded resource {name}", LogLevel.Debug); - } - } - } - catch (Exception exception) - { - - DebugLogger.LogDebug($"[ExternalEventLoader] Failed to load embedded resources from {target.FullName}: {exception}", LogLevel.Error, true); - } - } -} \ No newline at end of file diff --git a/AutoEvent-NWApi/Plugin.cs b/AutoEvent-NWApi/Plugin.cs deleted file mode 100644 index ea6acae6..00000000 --- a/AutoEvent-NWApi/Plugin.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System; -using System.IO; -using AutoEvent.Commands; -using AutoEvent.Interfaces; -using HarmonyLib; -using PluginAPI.Core.Attributes; -using PluginAPI.Enums; -using PluginAPI.Events; -using AutoEvent.Events.Handlers; -using Exiled.Loader; -using GameCore; -using MEC; -using PluginAPI.Core; -using Event = AutoEvent.Interfaces.Event; -using Log = PluginAPI.Core.Log; -using Paths = PluginAPI.Helpers.Paths; -using Server = PluginAPI.Core.Server; -#if EXILED -using Exiled.API.Features; - -#endif -namespace AutoEvent -{ -#if EXILED - public class AutoEvent : Plugin - { - public override System.Version Version => new System.Version(9, 1, 7); - public override string Name => "AutoEvent"; - public override string Author => "Created by KoT0XleB, extended by swd and sky, Co-Maintained by Redforce04"; - public static bool IsPlayedGames; - -#else - public class AutoEvent - { - [PluginConfig("Configs/autoevent.yml")] - public Config Config; - - [PluginConfig("Configs/translation.yml")] - public Translation Translation; -#endif - public const bool BetaRelease = true; // todo set beta to false before main release - /// - /// The location of the AutoEvent folder for schematics, music, external events and event config / translations. - /// - /// /home/container/.config/SCP Secret Laboratory/PluginAPI/plugins/global/AutoEvent/ - public static string BaseConfigPath { get; set;} - public static IEvent ActiveEvent; - public static AutoEvent Singleton; - public static Harmony HarmonyPatch; - public static bool Debug => DebugLogger.Debug; - EventHandler eventHandler; - -#if EXILED - public override void OnEnabled() -#else - [PluginPriority(LoadPriority.Low)] - [PluginEntryPoint("AutoEvent", "9.1.7", "An event manager plugin that allows you to run mini-games.", - "KoT0XleB and Redforce04")] - void OnEnabled() -#endif - { - if (!Config.IsEnabled) return; - if (BetaRelease) - { - Log.Warning("Warning: This release of AutoEvent is a Beta-Release." + - " If you encounter any bugs, please reach out to Redforce04 (redforce04) or KoT0XleB (spagettimen) via discord." + - " Alternatively, make an issue on our github (https://github.com/KoT0XleB/AutoEvent/). Have fun!"); - } - - // Call Costura first just to ensure dependencies are loaded. - // Also make sure there isn't anything that needs a dependency in this method. - CosturaUtility.Initialize(); - -#if !EXILED - // Root plugin path - AutoEvent.BaseConfigPath = Path.Combine(Paths.GlobalPlugins.Plugins, "AutoEvent"); -#else - AutoEvent.BaseConfigPath = Path.Combine(Exiled.API.Features.Paths.Configs, "AutoEvent"); -#endif - _startup(); - } - - private void _startup() - { - try - { - Singleton = this; - if (Config.IgnoredRoles.Contains(Config.LobbyRole)) - { - DebugLogger.LogDebug("The Lobby Role is also in ignored roles. This will break the game if not changed. The plugin will remove the lobby role from ignored roles.", LogLevel.Error, true); - Config.IgnoredRoles.Remove(Config.LobbyRole); - } - - FriendlyFireSystem.IsFriendlyFireEnabledByDefault = Server.FriendlyFire; - var debugLogger = new DebugLogger(Config.AutoLogDebug); - DebugLogger.Debug = Config.Debug; - if (DebugLogger.Debug) - { - DebugLogger.LogDebug($"Debug Mode Enabled", LogLevel.Info, true); - } - - try - { - HarmonyPatch = new Harmony("autoevent"); - HarmonyPatch.PatchAll(); - - } - catch (Exception e) - { - Log.Warning("Could not patch harmony methods."); - Log.Debug($"{e}"); - } - - eventHandler = new EventHandler(); - EventManager.RegisterEvents(eventHandler); - EventManager.RegisterEvents(this); - SCPSLAudioApi.Startup.SetupDependencies(); - - Servers.RemoteAdmin += eventHandler.OnRemoteAdmin; - try - { - DebugLogger.LogDebug($"Base Conf Path: {BaseConfigPath}"); - DebugLogger.LogDebug($"Configs paths: \n" + - $"{Config.SchematicsDirectoryPath}\n" + - $"{Config.MusicDirectoryPath}\n" + - $"{Config.ExternalEventsDirectoryPath}\n" + - $"{Config.EventConfigsDirectoryPath}\n"); - CreateDirectoryIfNotExists(BaseConfigPath); - CreateDirectoryIfNotExists(Config.SchematicsDirectoryPath); - CreateDirectoryIfNotExists(Config.MusicDirectoryPath); - CreateDirectoryIfNotExists(Config.ExternalEventsDirectoryPath); - CreateDirectoryIfNotExists(Config.EventConfigsDirectoryPath); - } - catch (Exception e) - { - DebugLogger.LogDebug($"An error has occured while trying to initialize directories.", LogLevel.Warn, true); - DebugLogger.LogDebug($"{e}"); - } - - - Event.RegisterInternalEvents(); - Loader.LoadEvents(); - Event.Events.AddRange(Loader.Events); - - DebugLogger.LogDebug( - Loader.Events.Count > 0 - ? $"[ExternalEventLoader] Loaded {Loader.Events.Count} external event{(Loader.Events.Count > 1 ? "s" : "")}." - : "No external events were found.", LogLevel.Info, true); - } - catch (Exception e) - { - Log.Warning("Caught an exception while starting plugin."); - Log.Debug($"{e}"); - - } - - Timing.CallDelayed(3f, () => - { - PermissionSystem.Load(); - }); - } - public static void CreateDirectoryIfNotExists(string directory, string subPath = "") - { - string path = ""; - try - { - path = subPath == "" ? directory : Path.Combine(directory, subPath); - // DebugLogger.LogDebug($"Filepath: {path}"); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - } - catch (Exception e) - { - DebugLogger.LogDebug($"An error has occured while trying to create a new directory.", LogLevel.Warn, true); - DebugLogger.LogDebug($"Path: {path}"); - DebugLogger.LogDebug($"{e}"); - } - } -#if !EXILED - [PluginUnload] - void OnDisabled() -#else - public override void OnDisabled() -#endif - { - Servers.RemoteAdmin -= eventHandler.OnRemoteAdmin; - eventHandler = null; - - EventManager.UnregisterEvents(this); - HarmonyPatch.UnpatchAll(); - Singleton = null; - } - } -} diff --git a/AutoEvent/API/Components/SchematicCollisionComponent.cs b/AutoEvent/API/Components/SchematicCollisionComponent.cs index 27661cd9..05af241e 100644 --- a/AutoEvent/API/Components/SchematicCollisionComponent.cs +++ b/AutoEvent/API/Components/SchematicCollisionComponent.cs @@ -14,8 +14,8 @@ using System.Collections.Generic; using System.Linq; using AdminToys; -using AutoEvent.API.Schematic; -using AutoEvent.API.Schematic.Objects; +using MER.Lite; +using MER.Lite.Objects; using Mirror; using PlayerStatsSystem; using PluginAPI.Core; diff --git a/AutoEvent/API/Extensions.cs b/AutoEvent/API/Extensions.cs index ecfe3e4b..60fe52a7 100644 --- a/AutoEvent/API/Extensions.cs +++ b/AutoEvent/API/Extensions.cs @@ -7,8 +7,8 @@ using PlayerRoles; using SCPSLAudioApi.AudioCore; using VoiceChat; -using AutoEvent.API.Schematic.Objects; -using AutoEvent.API.Schematic; +using MER.Lite.Objects; +using MER.Lite; using PluginAPI.Core; using InventorySystem.Items.Pickups; using PlayerStatsSystem; diff --git a/AutoEvent/API/RoleCount.cs b/AutoEvent/API/RoleCount.cs index 7873c50d..ea641f22 100644 --- a/AutoEvent/API/RoleCount.cs +++ b/AutoEvent/API/RoleCount.cs @@ -40,7 +40,7 @@ public RoleCount(int minimumPlayers = 0, int maximumPlayers = -1, float playerPe [Description($"The percentage of players that will be on the team. -1 to ignore.")] public float PlayerPercentage { get; set; } = 100; - public List GetPlayers([CanBeNull] List availablePlayers = null) + public List GetPlayers(bool alwaysLeaveOnePlayer = true, List? availablePlayers = null) { float percent = Player.GetPlayers().Count * (PlayerPercentage / 100f); int players = Mathf.Clamp((int)percent, MinimumPlayers, @@ -75,6 +75,11 @@ public List GetPlayers([CanBeNull] List availablePlayers = null) DebugLogger.LogDebug("Could not assign player to list.", LogLevel.Warn); DebugLogger.LogDebug($"{e}", LogLevel.Debug); } + if(alwaysLeaveOnePlayer && validPlayers.Count >= (availablePlayers ?? Player.GetPlayers()).Count) + { + var plyToRemove = validPlayers.RandomItem(); + validPlayers.Remove(plyToRemove); + } return validPlayers; } } \ No newline at end of file diff --git a/AutoEvent/AutoEvent.csproj b/AutoEvent/AutoEvent.csproj index bc6ca5c6..833cf5cf 100644 --- a/AutoEvent/AutoEvent.csproj +++ b/AutoEvent/AutoEvent.csproj @@ -9,6 +9,7 @@ enable Release AnyCPU + 9.2.0 ..\bin\Release\Exiled @@ -34,6 +35,9 @@ default + + true + all @@ -78,4 +82,26 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AutoEvent/AutoEvent.sln b/AutoEvent/AutoEvent.sln index ce9ffeb8..13707205 100644 --- a/AutoEvent/AutoEvent.sln +++ b/AutoEvent/AutoEvent.sln @@ -5,6 +5,10 @@ VisualStudioVersion = 17.5.33627.172 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoEvent", "AutoEvent.csproj", "{3C3FC008-22E1-4B28-BA50-A241B30CC216}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SchematicApi", "SchematicApi\SchematicApi.csproj", "{580DFED2-B2D7-4B89-B245-D60246BCFB79}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerupApi", "PowerupApi\PowerupApi.csproj", "{1B07FE64-A112-499D-8A55-67EE912B1CB7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release NWApi|Any CPU = Release NWApi|Any CPU @@ -15,6 +19,14 @@ Global {3C3FC008-22E1-4B28-BA50-A241B30CC216}.Release NWApi|Any CPU.Build.0 = Release NWApi|Any CPU {3C3FC008-22E1-4B28-BA50-A241B30CC216}.Release Exiled|Any CPU.ActiveCfg = Release EXILED|Any CPU {3C3FC008-22E1-4B28-BA50-A241B30CC216}.Release Exiled|Any CPU.Build.0 = Release EXILED|Any CPU + {580DFED2-B2D7-4B89-B245-D60246BCFB79}.Release NWApi|Any CPU.ActiveCfg = Release|Any CPU + {580DFED2-B2D7-4B89-B245-D60246BCFB79}.Release NWApi|Any CPU.Build.0 = Release|Any CPU + {580DFED2-B2D7-4B89-B245-D60246BCFB79}.Release Exiled|Any CPU.ActiveCfg = Release|Any CPU + {580DFED2-B2D7-4B89-B245-D60246BCFB79}.Release Exiled|Any CPU.Build.0 = Release|Any CPU + {1B07FE64-A112-499D-8A55-67EE912B1CB7}.Release NWApi|Any CPU.ActiveCfg = Release|Any CPU + {1B07FE64-A112-499D-8A55-67EE912B1CB7}.Release NWApi|Any CPU.Build.0 = Release|Any CPU + {1B07FE64-A112-499D-8A55-67EE912B1CB7}.Release Exiled|Any CPU.ActiveCfg = Release|Any CPU + {1B07FE64-A112-499D-8A55-67EE912B1CB7}.Release Exiled|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AutoEvent/Commands/Config/Config.cs b/AutoEvent/Commands/Config/Config.cs index 6261a23b..c0ae8caa 100644 --- a/AutoEvent/Commands/Config/Config.cs +++ b/AutoEvent/Commands/Config/Config.cs @@ -65,7 +65,7 @@ protected override bool ExecuteParent(ArraySegment arguments, ICommandSe public override string Command => nameof(Config); public override string[] Aliases => Array.Empty(); - public override string Description => "Allows modifying configs before and during events.."; + public override string Description => "Allows modifying configs before and during events"; } /* diff --git a/AutoEvent/Commands/Debug/Debug.cs b/AutoEvent/Commands/Debug/Debug.cs index adddebd8..c8e23039 100644 --- a/AutoEvent/Commands/Debug/Debug.cs +++ b/AutoEvent/Commands/Debug/Debug.cs @@ -73,5 +73,5 @@ protected override bool ExecuteParent(ArraySegment arguments, ICommandSe public override string Command => nameof(global::AutoEvent.Commands.Debug); public override string[] Aliases => Array.Empty(); - public override string Description => "Runs various debug functions."; + public override string Description => "Runs various debug functions"; } \ No newline at end of file diff --git a/AutoEvent/Commands/Debug/PowerupCommand.cs b/AutoEvent/Commands/Debug/PowerupCommand.cs index 42dbcb96..e43acd83 100644 --- a/AutoEvent/Commands/Debug/PowerupCommand.cs +++ b/AutoEvent/Commands/Debug/PowerupCommand.cs @@ -17,6 +17,7 @@ using AutoEvent.Interfaces; using CommandSystem; using PluginAPI.Core; +using Powerups; using UnityEngine; using Player = PluginAPI.Core.Player; #if EXILED @@ -28,7 +29,7 @@ namespace AutoEvent.Commands.Debug; public class PowerupCommand : ICommand, IPermission, IUsageProvider { - public string Command => nameof(Interfaces.Powerup); + public string Command => "Powerup"; public string[] Aliases => Array.Empty(); public string Description => "Manages powerups."; public string[] Usage => new []{ "Give / Remove / Spawn / List", "Player / Powerup", "Powerup / Position X", "Position Y", "Position Z" }; @@ -47,7 +48,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s goto usage; } Player ply = null!; - Interfaces.Powerup powerup = null!; + Powerup powerup = null!; switch (arguments.At(0).ToLower()) { @@ -142,7 +143,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s case 1: if (arguments.At(i) == "*") { - foreach (Interfaces.Powerup powerupInstance in PowerupManager.RegisteredPowerups) + foreach (Powerup powerupInstance in PowerupManager.RegisteredPowerups) { if (powerupInstance.ActivePlayers.ContainsKey(ply)) { diff --git a/AutoEvent/Commands/List.cs b/AutoEvent/Commands/List.cs index 1f741671..9d76bddd 100644 --- a/AutoEvent/Commands/List.cs +++ b/AutoEvent/Commands/List.cs @@ -18,7 +18,7 @@ public List() // Log.Debug("Skipping Registering List Command"); } public string Command => nameof(List); - public string Description => "Shows a list of all the events that can be started."; + public string Description => "Shows a list of all the events that can be started"; public string[] Aliases => new string[] { }; public string Permission { get; set; } = "ev.list"; public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) @@ -28,6 +28,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s response = "You do not have permission to use this command!"; return false; } + StringBuilder builder = new StringBuilder(); if (!IsConsoleCommandSender) { @@ -75,11 +76,10 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s builder.AppendLine($"{(!IsConsoleCommandSender ? "" : "")}[{(!IsConsoleCommandSender ? $"" : "")}==Exiled Events=={(!IsConsoleCommandSender ? "" : "")}]"); break; } - + foreach (Event ev in eventlist.Value) { - - + if (ev is IHidden) continue; if (!IsConsoleCommandSender) builder.AppendLine( $"{ev.Name} [{ev.CommandName}]: {ev.Description}"); @@ -103,6 +103,5 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s response = builder.ToString(); return true; } - } } diff --git a/AutoEvent/Commands/Lobby.cs b/AutoEvent/Commands/Lobby.cs new file mode 100644 index 00000000..b5b76597 --- /dev/null +++ b/AutoEvent/Commands/Lobby.cs @@ -0,0 +1,66 @@ +using AutoEvent.Interfaces; +using CommandSystem; +using System; +using System.Linq; +using AutoEvent.API; +using MEC; +using PluginAPI.Core; +using Utils.NonAllocLINQ; +using PlayerRoles; +#if EXILED +using Exiled.Permissions.Extensions; +#endif + +namespace AutoEvent.Commands +{ + internal class Lobby// : ICommand, IPermission + { + public string Command => nameof(Lobby); + public string Description => "Starting a lobby in which the winner chooses a mini-game"; + public string[] Aliases => new string[] { }; + public string Permission { get; set; } = "ev.lobby"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + if (!sender.CheckPermission(((IPermission)this).Permission, out bool IsConsoleCommandSender)) + { + response = "You do not have permission to use this command!"; + return false; + } + if (AutoEvent.ActiveEvent != null) + { + response = $"The mini-game {AutoEvent.ActiveEvent.Name} is already running!"; + return false; + } + + Event lobby = Event.GetEvent("Lobby"); + if (lobby == null) + { + response = $"The lobby is not found."; + return false; + } + + Round.IsLocked = true; + + if (!Round.IsRoundStarted) + { + Round.Start(); + + Timing.CallDelayed(2f, () => { + + lobby.StartEvent(); + AutoEvent.ActiveEvent = lobby; + }); + } + else + { + lobby.StartEvent(); + AutoEvent.ActiveEvent = lobby; + } + + response = $"The lobby event has started!"; + return true; + } + + } +} diff --git a/AutoEvent/Commands/MainCommand.cs b/AutoEvent/Commands/MainCommand.cs index 439bfc0d..ac05015c 100644 --- a/AutoEvent/Commands/MainCommand.cs +++ b/AutoEvent/Commands/MainCommand.cs @@ -20,6 +20,8 @@ public override void LoadGeneratedCommands() RegisterCommand(new List()); RegisterCommand(new Run()); RegisterCommand(new Stop()); + //RegisterCommand(new Lobby()); + //RegisterCommand(new Vote()); RegisterCommand(new Volume()); RegisterCommand(new Reload.Reload()); RegisterCommand(new Debug.Debug()); diff --git a/AutoEvent/Commands/Reload/Reload.cs b/AutoEvent/Commands/Reload/Reload.cs index 319e699c..ab19dd10 100644 --- a/AutoEvent/Commands/Reload/Reload.cs +++ b/AutoEvent/Commands/Reload/Reload.cs @@ -56,5 +56,5 @@ protected override bool ExecuteParent(ArraySegment arguments, ICommandSe public override string Command => nameof(Reload); public override string[] Aliases => Array.Empty(); - public override string Description => "Reloads different aspects of the plugin and events."; + public override string Description => "Reloads different aspects of the plugin and events"; } \ No newline at end of file diff --git a/AutoEvent/Commands/Run.cs b/AutoEvent/Commands/Run.cs index dde72d30..c055fd33 100644 --- a/AutoEvent/Commands/Run.cs +++ b/AutoEvent/Commands/Run.cs @@ -15,9 +15,9 @@ namespace AutoEvent.Commands internal class Run : ICommand, IUsageProvider, IPermission { public string Command => nameof(Run); - public string Description => "Run the event, takes on 1 argument - the command name of the event."; + public string Description => "Run the event, takes on 1 argument - the command name of the event"; public string[] Aliases => new []{ "start", "play", "begin" }; - public string[] Usage => new string[] { "[Event Name]" }; + public string[] Usage => new string[] { "Event Name" }; public string Permission { get; set; } = "ev.run"; public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) @@ -40,11 +40,12 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s } Event ev = Event.GetEvent(arguments.At(0)); - if (ev == null) + if (ev == null || ev is IHidden) { response = $"The mini-game {arguments.At(0)} is not found."; return false; } + string conf = ""; EventConfig? config = null; if (arguments.Count >= 2) diff --git a/AutoEvent/Commands/Volume.cs b/AutoEvent/Commands/Volume.cs index 0409979d..18d30591 100644 --- a/AutoEvent/Commands/Volume.cs +++ b/AutoEvent/Commands/Volume.cs @@ -23,7 +23,7 @@ namespace AutoEvent.Commands; public class Volume : ICommand, IUsageProvider, IPermission { public string Command => nameof(Volume); - public string Description => "Set the global music volume, takes on 1 argument - the volume from 0% - 200%."; + public string Description => "Set the global music volume, takes on 1 argument - the volume from 0%-200%"; public string[] Aliases => new string[] { }; public string[] Usage => new string[] { "Volume %" }; public string Permission { get; set; } = "ev.volume"; diff --git a/AutoEvent/Commands/Vote.cs b/AutoEvent/Commands/Vote.cs new file mode 100644 index 00000000..1189a7c7 --- /dev/null +++ b/AutoEvent/Commands/Vote.cs @@ -0,0 +1,88 @@ +using AutoEvent.Interfaces; +using CommandSystem; +using System; +using System.Linq; +using AutoEvent.API; +using MEC; +using PluginAPI.Core; +using PlayerRoles; +#if EXILED +using Exiled.Permissions.Extensions; +#endif + +namespace AutoEvent.Commands +{ + internal class Vote// : ICommand, IUsageProvider, IPermission + { + public string Command => nameof(Vote); + public string Description => "Starts voting for mini-game, 1 argument - the command name of the event"; + public string[] Aliases => new string[] { }; + public string[] Usage => new string[] { "Event Name" }; + public string Permission { get; set; } = "ev.vote"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + if (!sender.CheckPermission(((IPermission)this).Permission, out bool IsConsoleCommandSender)) + { + response = "You do not have permission to use this command!"; + return false; + } + if (AutoEvent.ActiveEvent != null) + { + response = $"The mini-game {AutoEvent.ActiveEvent.Name} is already running!"; + return false; + } + + if (arguments.Count < 1) + { + response = "Only 1 argument is needed - the command name of the event!"; + return false; + } + + Event ev = Event.GetEvent(arguments.At(0)); + if (ev == null || ev is IHidden) + { + response = $"The mini-game {arguments.At(0)} is not found."; + return false; + } + + Event vote = Event.GetEvent("Vote"); + if (vote == null) + { + response = $"The vote is not found."; + return false; + } + + IVote comp = vote as IVote; + if (comp == null) + { + response = $"The IVote is not found."; + return false; + } + + comp.NewEvent = ev; + Round.IsLocked = true; + + if (!Round.IsRoundStarted) + { + Round.Start(); + + Timing.CallDelayed(2f, () => { + + Extensions.TeleportEnd(); + vote.StartEvent(); + AutoEvent.ActiveEvent = vote; + }); + } + else + { + vote.StartEvent(); + AutoEvent.ActiveEvent = vote; + } + + response = $"The vote {ev.Name} has started!"; + return true; + } + + } +} diff --git a/AutoEvent/FodyWeavers.xml b/AutoEvent/FodyWeavers.xml index 13ea034e..447bbee0 100644 --- a/AutoEvent/FodyWeavers.xml +++ b/AutoEvent/FodyWeavers.xml @@ -7,6 +7,8 @@ System.ComponentModel.DataAnnotations YamlDotNet NVorbis + PowerupApi + SchematicApi diff --git a/AutoEvent/Games/Battle/Features/RandomClass.cs b/AutoEvent/Games/Battle/Features/RandomClass.cs index 56a3d460..2ae8b2f3 100644 --- a/AutoEvent/Games/Battle/Features/RandomClass.cs +++ b/AutoEvent/Games/Battle/Features/RandomClass.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using PluginAPI.Core; using System.Linq; using AutoEvent.Games.Example; diff --git a/AutoEvent/Games/Battle/Plugin.cs b/AutoEvent/Games/Battle/Plugin.cs index aa9339fb..66da4538 100644 --- a/AutoEvent/Games/Battle/Plugin.cs +++ b/AutoEvent/Games/Battle/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using MEC; using PlayerRoles; diff --git a/AutoEvent/Games/Boss/Features/RandomClass.cs b/AutoEvent/Games/Boss/Features/RandomClass.cs index a67ca905..d140f373 100644 --- a/AutoEvent/Games/Boss/Features/RandomClass.cs +++ b/AutoEvent/Games/Boss/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using PluginAPI.Core; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Boss/Plugin.cs b/AutoEvent/Games/Boss/Plugin.cs index 13c0f19a..36d1ae95 100644 --- a/AutoEvent/Games/Boss/Plugin.cs +++ b/AutoEvent/Games/Boss/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using PluginAPI.Core; @@ -100,7 +100,7 @@ protected override void CountdownFinished() { _boss = new List(); StartAudio(); - foreach (var player in Config.BossCount.GetPlayers()) + foreach (var player in Config.BossCount.GetPlayers(true)) { _boss.Add(player); player.GiveLoadout(Config.BossLoadouts); diff --git a/AutoEvent/Games/DeathParty/Features/RandomClass.cs b/AutoEvent/Games/DeathParty/Features/RandomClass.cs index ff6db92a..f56a3e44 100644 --- a/AutoEvent/Games/DeathParty/Features/RandomClass.cs +++ b/AutoEvent/Games/DeathParty/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/DeathParty/Plugin.cs b/AutoEvent/Games/DeathParty/Plugin.cs index a3a54f37..8a245df3 100644 --- a/AutoEvent/Games/DeathParty/Plugin.cs +++ b/AutoEvent/Games/DeathParty/Plugin.cs @@ -7,7 +7,7 @@ using PlayerRoles; using PluginAPI.Core; using PluginAPI.Events; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using AutoEvent.Games.Infection; using AutoEvent.Interfaces; diff --git a/AutoEvent/Games/Deathmatch/Extensions/RandomClass.cs b/AutoEvent/Games/Deathmatch/Extensions/RandomClass.cs index 283e17d7..d3e7477c 100644 --- a/AutoEvent/Games/Deathmatch/Extensions/RandomClass.cs +++ b/AutoEvent/Games/Deathmatch/Extensions/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Collections.Generic; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Deathmatch/Plugin.cs b/AutoEvent/Games/Deathmatch/Plugin.cs index 3261e166..0361a324 100644 --- a/AutoEvent/Games/Deathmatch/Plugin.cs +++ b/AutoEvent/Games/Deathmatch/Plugin.cs @@ -1,5 +1,5 @@ using CustomPlayerEffects; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using PluginAPI.Core; diff --git a/AutoEvent/Games/Example/Features/RandomClass.cs b/AutoEvent/Games/Example/Features/RandomClass.cs index 8d027ce2..3a280f5f 100644 --- a/AutoEvent/Games/Example/Features/RandomClass.cs +++ b/AutoEvent/Games/Example/Features/RandomClass.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using PluginAPI.Core; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/FallDown/Configs/FallDownConfigPresets.cs b/AutoEvent/Games/FallDown/Configs/FallDownConfigPresets.cs index 7b52a13b..cb7bbb68 100644 --- a/AutoEvent/Games/FallDown/Configs/FallDownConfigPresets.cs +++ b/AutoEvent/Games/FallDown/Configs/FallDownConfigPresets.cs @@ -14,7 +14,7 @@ namespace AutoEvent.Games.Infection; public static class FallDownConfigPresets { - public static FallDownConfig PlatformWarning { get; } = new FallDownConfig() + public static FallDownConfig PlatformWarning() => new FallDownConfig() { PlatformsHaveColorWarning = true }; diff --git a/AutoEvent/Games/FallDown/Extensions/RandomClass.cs b/AutoEvent/Games/FallDown/Extensions/RandomClass.cs index dcc6cc06..83b0e270 100644 --- a/AutoEvent/Games/FallDown/Extensions/RandomClass.cs +++ b/AutoEvent/Games/FallDown/Extensions/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/FallDown/Plugin.cs b/AutoEvent/Games/FallDown/Plugin.cs index 328fe71a..dd431417 100644 --- a/AutoEvent/Games/FallDown/Plugin.cs +++ b/AutoEvent/Games/FallDown/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using PluginAPI.Core; @@ -22,7 +22,7 @@ public class Plugin : Event, IEventSound, IEventMap, IInternalEvent public override string Author { get; set; } = "KoT0XleB"; public override string CommandName { get; set; } = AutoEvent.Singleton.Translation.FallTranslate.FallCommandName; [EventConfig] public FallDownConfig Config { get; set; } = null; - [EventConfig] public FallDownConfig Warning => FallDownConfigPresets.PlatformWarning; + [EventConfig] public FallDownConfig Warning => FallDownConfigPresets.PlatformWarning(); public MapInfo MapInfo { get; set; } = new MapInfo() {MapName = "FallDown", Position = new Vector3(10f, 1020f, -43.68f) }; public SoundInfo SoundInfo { get; set; } = new SoundInfo() diff --git a/AutoEvent/Games/FinishWay/Extensions/RandomClass.cs b/AutoEvent/Games/FinishWay/Extensions/RandomClass.cs index bbacffb7..2b50624a 100644 --- a/AutoEvent/Games/FinishWay/Extensions/RandomClass.cs +++ b/AutoEvent/Games/FinishWay/Extensions/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/FinishWay/Plugin.cs b/AutoEvent/Games/FinishWay/Plugin.cs index a0833f54..4f8be8a4 100644 --- a/AutoEvent/Games/FinishWay/Plugin.cs +++ b/AutoEvent/Games/FinishWay/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using MEC; using PlayerRoles; diff --git a/AutoEvent/Games/Football/Features/RandomClass.cs b/AutoEvent/Games/Football/Features/RandomClass.cs index 341190e7..908b7c36 100644 --- a/AutoEvent/Games/Football/Features/RandomClass.cs +++ b/AutoEvent/Games/Football/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Football/Plugin.cs b/AutoEvent/Games/Football/Plugin.cs index 9bf2fab3..ce5e989f 100644 --- a/AutoEvent/Games/Football/Plugin.cs +++ b/AutoEvent/Games/Football/Plugin.cs @@ -8,7 +8,7 @@ using AutoEvent.Games.Football.Features; using PluginAPI.Events; using PluginAPI.Core; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using AutoEvent.Games.Infection; using AutoEvent.Interfaces; diff --git a/AutoEvent/Games/Glass/Features/RandomClass.cs b/AutoEvent/Games/Glass/Features/RandomClass.cs index 3056b1c3..b9ddc839 100644 --- a/AutoEvent/Games/Glass/Features/RandomClass.cs +++ b/AutoEvent/Games/Glass/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Glass/Plugin.cs b/AutoEvent/Games/Glass/Plugin.cs index 0490b125..544951aa 100644 --- a/AutoEvent/Games/Glass/Plugin.cs +++ b/AutoEvent/Games/Glass/Plugin.cs @@ -11,7 +11,7 @@ using CustomPlayerEffects; using PluginAPI.Core; using PluginAPI.Events; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using AutoEvent.Games.Infection; using AutoEvent.Interfaces; diff --git a/AutoEvent/Games/GunGame/Plugin.cs b/AutoEvent/Games/GunGame/Plugin.cs index d323afb9..5e6fbad8 100644 --- a/AutoEvent/Games/GunGame/Plugin.cs +++ b/AutoEvent/Games/GunGame/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using MEC; using PlayerRoles; diff --git a/AutoEvent/Games/HideAndSeek/Features/RandomClass.cs b/AutoEvent/Games/HideAndSeek/Features/RandomClass.cs index 2d401fa6..9d27da92 100644 --- a/AutoEvent/Games/HideAndSeek/Features/RandomClass.cs +++ b/AutoEvent/Games/HideAndSeek/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/HideAndSeek/Plugin.cs b/AutoEvent/Games/HideAndSeek/Plugin.cs index 31121c0e..a13d63c1 100644 --- a/AutoEvent/Games/HideAndSeek/Plugin.cs +++ b/AutoEvent/Games/HideAndSeek/Plugin.cs @@ -1,5 +1,5 @@ using CustomPlayerEffects; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using PluginAPI.Core; @@ -130,7 +130,7 @@ private IEnumerator TagPeriod() private void SelectPlayers() { List playersToChoose = Player.GetPlayers().Where(x => x.IsAlive).ToList(); - foreach(Player ply in Config.TaggerCount.GetPlayers(playersToChoose)) + foreach(Player ply in Config.TaggerCount.GetPlayers(true, playersToChoose)) { ply.GiveLoadout(Config.TaggerLoadouts); var item = ply.AddItem(Config.TaggerWeapon); diff --git a/AutoEvent/Games/Infection/Extensions/RandomClass.cs b/AutoEvent/Games/Infection/Extensions/RandomClass.cs index 81d5e571..e0830cd0 100644 --- a/AutoEvent/Games/Infection/Extensions/RandomClass.cs +++ b/AutoEvent/Games/Infection/Extensions/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Infection/Plugin.cs b/AutoEvent/Games/Infection/Plugin.cs index 415591b7..47e6df45 100644 --- a/AutoEvent/Games/Infection/Plugin.cs +++ b/AutoEvent/Games/Infection/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using MEC; using PlayerRoles; diff --git a/AutoEvent/Games/Jail/Extensions/JailRandom.cs b/AutoEvent/Games/Jail/Extensions/JailRandom.cs index 9c1ea423..536208a6 100644 --- a/AutoEvent/Games/Jail/Extensions/JailRandom.cs +++ b/AutoEvent/Games/Jail/Extensions/JailRandom.cs @@ -1,5 +1,5 @@ using System; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Jail/Plugin.cs b/AutoEvent/Games/Jail/Plugin.cs index 6f1605ec..a7285a93 100644 --- a/AutoEvent/Games/Jail/Plugin.cs +++ b/AutoEvent/Games/Jail/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using System; @@ -159,7 +159,7 @@ protected override void OnStart() } } - foreach (Player ply in Config.JailorRoleCount.GetPlayers()) + foreach (Player ply in Config.JailorRoleCount.GetPlayers(true)) { ply.GiveLoadout(Config.JailorLoadouts, LoadoutFlags.IgnoreWeapons); try diff --git a/AutoEvent/Games/Knives/Features/RandomClass.cs b/AutoEvent/Games/Knives/Features/RandomClass.cs index 6dcffe2e..54c08d71 100644 --- a/AutoEvent/Games/Knives/Features/RandomClass.cs +++ b/AutoEvent/Games/Knives/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Knives/Plugin.cs b/AutoEvent/Games/Knives/Plugin.cs index cd4a6988..ad00d0a9 100644 --- a/AutoEvent/Games/Knives/Plugin.cs +++ b/AutoEvent/Games/Knives/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using PluginAPI.Core; diff --git a/AutoEvent/Games/Lava/Features/RandomClass.cs b/AutoEvent/Games/Lava/Features/RandomClass.cs index 764e040d..02b13d71 100644 --- a/AutoEvent/Games/Lava/Features/RandomClass.cs +++ b/AutoEvent/Games/Lava/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Lava/Plugin.cs b/AutoEvent/Games/Lava/Plugin.cs index 1871e9e1..6506bcb0 100644 --- a/AutoEvent/Games/Lava/Plugin.cs +++ b/AutoEvent/Games/Lava/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using MEC; using PlayerRoles; diff --git a/AutoEvent/Games/Line/Plugin.cs b/AutoEvent/Games/Line/Plugin.cs index c36d9bca..2ef29f36 100644 --- a/AutoEvent/Games/Line/Plugin.cs +++ b/AutoEvent/Games/Line/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using MEC; using PlayerRoles; diff --git a/AutoEvent/Games/Lobby/Plugin.cs b/AutoEvent/Games/Lobby/Plugin.cs index 03aa9f7f..80ee5e1b 100644 --- a/AutoEvent/Games/Lobby/Plugin.cs +++ b/AutoEvent/Games/Lobby/Plugin.cs @@ -6,10 +6,12 @@ using System.Linq; using Event = AutoEvent.Interfaces.Event; using Player = PluginAPI.Core.Player; +using PluginAPI.Core; +using MEC; namespace AutoEvent.Games.Lobby { - public class Plugin : Event, IEventMap, IEventSound, IInternalEvent + public class Plugin : Event, IEventMap, IEventSound, IHidden, IVote { public override string Name { get; set; } = "Lobby"; public override string Description { get; set; } = "A lobby in which one quick player chooses a mini-game."; @@ -24,7 +26,9 @@ public class Plugin : Event, IEventMap, IEventSound, IInternalEvent Player _chooser { get; set; } List _spawnpoints { get; set; } List _teleports { get; set; } - List _platformes { get; set; } + Dictionary _platformes { get; set; } + public List _eventList { get; set; } + public Event NewEvent { get; set; } protected override void RegisterEvents() { @@ -64,7 +68,7 @@ protected void InitGameObjects() { case "Spawnpoint": _spawnpoints.Add(obj); break; case "Teleport": _teleports.Add(obj); break; - case "Platform": _platformes.Add(obj); break; + case "Platform": _platformes.Add(obj, obj.transform.parent.name); break; } } catch (Exception e) @@ -77,7 +81,7 @@ protected void InitGameObjects() protected override bool IsRoundDone() { - DebugLogger.LogDebug($"Lobby state is {_state}"); + DebugLogger.LogDebug($"Lobby state is {_state} and {(NewEvent is null ? "null" : NewEvent.Name)}"); if (_state == LobbyState.Waiting) return false; @@ -94,9 +98,8 @@ protected override bool IsRoundDone() protected override void ProcessFrame() { string message = "Get ready to run to the center and choose a mini game"; - string time = $"{(16 - EventTime.Seconds):00}"; - if (_state == LobbyState.Waiting && EventTime.TotalSeconds >= 15) + if (_state == LobbyState.Waiting && EventTime.TotalSeconds >= 5) { GameObject.Destroy(MapInfo.Map.AttachedBlocks.First(r => r.name == "Wall").gameObject); EventTime = new(); @@ -106,7 +109,7 @@ protected override void ProcessFrame() if (_state == LobbyState.Running) { message = "RUN"; - if (EventTime.TotalSeconds <= 15) + if (EventTime.TotalSeconds <= 10) { foreach (Player player in Player.GetPlayers()) { @@ -135,31 +138,36 @@ protected override void ProcessFrame() { foreach (var platform in _platformes) { - if (Vector3.Distance(platform.transform.position, _chooser.Position) < 2) + if (Vector3.Distance(platform.Key.transform.position, _chooser.Position) < 2) { - // ev run mg + NewEvent = Event.GetEvent(platform.Value); _state = LobbyState.Ending; } } } else { - // Random mg + NewEvent = Event.GetEvent(_platformes.ToList().RandomItem().Value); _state = LobbyState.Ending; } } Extensions.Broadcast($"Lobby\n" + $"{message}\n" + - $"players = {Player.GetPlayers().Count()} | {time} seconds left!", 1); + $"{Player.GetPlayers().Count()} players in the lobby", 1); } protected override void OnFinished() { DebugLogger.LogDebug($"Lobby is finished"); Extensions.Broadcast($"The lobby is finished.\n" + - $"The player {_chooser.Nickname} chose the %name% mini-game.\n" + + $"The player {_chooser.Nickname} chose the {NewEvent.Name} mini-game.\n" + $"Total {Player.GetPlayers().Count()} players in the lobby", 10); + + Timing.CallDelayed(10.1f, () => + { + Server.RunCommand($"ev run {NewEvent.CommandName}"); + }); } } } diff --git a/AutoEvent/Games/Puzzle/Configs/PuzzleConfig.cs b/AutoEvent/Games/Puzzle/Configs/PuzzleConfig.cs index 56dab876..c3d5a444 100644 --- a/AutoEvent/Games/Puzzle/Configs/PuzzleConfig.cs +++ b/AutoEvent/Games/Puzzle/Configs/PuzzleConfig.cs @@ -44,9 +44,12 @@ public class PuzzleConfig : EventConfig [Description("Uses random platform colors instead of green and magenta.")] public bool UseRandomPlatformColors { get; set; } = false; [Description("How far the platforms are spread out.")] - public DifficultyItem PlatformSpread { get; set; } = new DifficultyItem(1, 5f); + public DifficultyItem PlatformSpread { get; set; } = new DifficultyItem(5, 30f); + [Description("Used for color selection. This will be reworked in the future.")] public DifficultyItem HueDifficulty { get; set; } = new DifficultyItem(1, 0.6f); + [Description("Used for color selection. This will be reworked in the future.")] public DifficultyItem SaturationDifficulty { get; set; } = new DifficultyItem(1, 0.6f); + [Description("Used for color selection. This will be reworked in the future.")] public DifficultyItem VDifficulty { get; set; } = new DifficultyItem(1, 0.6f); } \ No newline at end of file diff --git a/AutoEvent/Games/Puzzle/Features/RandomClass.cs b/AutoEvent/Games/Puzzle/Features/RandomClass.cs index abdb42d0..8cb98451 100644 --- a/AutoEvent/Games/Puzzle/Features/RandomClass.cs +++ b/AutoEvent/Games/Puzzle/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Puzzle/Plugin.cs b/AutoEvent/Games/Puzzle/Plugin.cs index e581ccd7..2e459092 100644 --- a/AutoEvent/Games/Puzzle/Plugin.cs +++ b/AutoEvent/Games/Puzzle/Plugin.cs @@ -4,7 +4,7 @@ using System.Linq; using MEC; using PlayerRoles; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using UnityEngine; using PluginAPI.Core; using PluginAPI.Events; diff --git a/AutoEvent/Games/Survival/Extensions/RandomClass.cs b/AutoEvent/Games/Survival/Extensions/RandomClass.cs index fb16947e..fb070d88 100644 --- a/AutoEvent/Games/Survival/Extensions/RandomClass.cs +++ b/AutoEvent/Games/Survival/Extensions/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Collections.Generic; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Survival/Plugin.cs b/AutoEvent/Games/Survival/Plugin.cs index f650405b..4d313343 100644 --- a/AutoEvent/Games/Survival/Plugin.cs +++ b/AutoEvent/Games/Survival/Plugin.cs @@ -1,5 +1,5 @@ using CustomPlayerEffects; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using MEC; using PlayerRoles; using PluginAPI.Core; @@ -88,7 +88,7 @@ protected override void CountdownFinished() { Extensions.PlayAudio("Zombie2.ogg", 7, true, Name); - List players =Config.Zombies.GetPlayers(); + List players = Config.Zombies.GetPlayers(true); foreach (Player x in players) { DebugLogger.LogDebug($"Making player {x.Nickname} a zombie."); diff --git a/AutoEvent/Games/Versus/Features/RandomClass.cs b/AutoEvent/Games/Versus/Features/RandomClass.cs index b2bc9d0a..f4ce3b7f 100644 --- a/AutoEvent/Games/Versus/Features/RandomClass.cs +++ b/AutoEvent/Games/Versus/Features/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/Versus/Plugin.cs b/AutoEvent/Games/Versus/Plugin.cs index 74e5ee51..70c44f4b 100644 --- a/AutoEvent/Games/Versus/Plugin.cs +++ b/AutoEvent/Games/Versus/Plugin.cs @@ -4,7 +4,7 @@ using AutoEvent.API.Enums; using MEC; using PlayerRoles; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using UnityEngine; using PluginAPI.Core; using PluginAPI.Events; diff --git a/AutoEvent/Games/Vote/Plugin.cs b/AutoEvent/Games/Vote/Plugin.cs index dcb60095..aac84fe7 100644 --- a/AutoEvent/Games/Vote/Plugin.cs +++ b/AutoEvent/Games/Vote/Plugin.cs @@ -4,12 +4,14 @@ using System.Linq; using AutoEvent.Interfaces; using AutoEvent.Events.Handlers; +using MEC; +using PluginAPI.Core; using Event = AutoEvent.Interfaces.Event; using Player = PluginAPI.Core.Player; namespace AutoEvent.Games.Vote { - public class Plugin : Event, IEventSound, IInternalEvent + public class Plugin : Event, IEventSound, IHidden, IVote { public override string Name { get; set; } = "Vote"; public override string Description { get; set; } = "Start voting for the mini-game."; @@ -20,6 +22,8 @@ public class Plugin : Event, IEventSound, IInternalEvent private EventHandler EventHandler { get; set; } public Dictionary _voteList { get; set; } private int _voteTime = 30; + public static string EventName { get; set; } + public Event NewEvent { get; set; } protected override void RegisterEvents() { @@ -56,8 +60,8 @@ protected override void ProcessFrame() var count = Player.GetPlayers().Count(r => r.Role == RoleTypeId.ClassD); var time = $"{(_voteTime - EventTime.Seconds):00}"; - Extensions.Broadcast($"Vote: Press [Alt] Pros or twice Cons\n" + - $"{_voteList.Count(r => r.Value == true)} of {_voteList.Count} players for Mini-Game %Name%\n" + + Extensions.Broadcast($"Vote: Press [Alt] Pros or [Alt]x2 Cons\n" + + $"{_voteList.Count(r => r.Value == true)} of {_voteList.Count} players for {NewEvent.Name}\n" + $"{time} seconds left!", 1); } @@ -66,14 +70,17 @@ protected override void OnFinished() string results; if (_voteList.Count(r => r.Value == true) > _voteList.Count(r => r.Value == false)) { - results = "Mini-Game %Name% will start soon."; - // timing -> ev run name - // idea: do I need to make an auto discord message about voting? About launching a mini-game? + results = $"{NewEvent.Name} will start soon."; + + // There is no way to change PostRoundDelay time to 5 second + Timing.CallDelayed(10.1f, () => + { + Server.RunCommand($"ev run {NewEvent.CommandName}"); + }); } else { - results = "Mini-Game %Name% will not start."; - // nothing + results = $"{NewEvent.Name} will not start."; } Extensions.Broadcast($"Vote: End of voting\n" + diff --git a/AutoEvent/Games/ZombieEscape/Extensions/RandomClass.cs b/AutoEvent/Games/ZombieEscape/Extensions/RandomClass.cs index 3aadd1fa..acb8d3b4 100644 --- a/AutoEvent/Games/ZombieEscape/Extensions/RandomClass.cs +++ b/AutoEvent/Games/ZombieEscape/Extensions/RandomClass.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using System.Collections.Generic; using System.Linq; using UnityEngine; diff --git a/AutoEvent/Games/ZombieEscape/Plugin.cs b/AutoEvent/Games/ZombieEscape/Plugin.cs index 050b2e01..250508bc 100644 --- a/AutoEvent/Games/ZombieEscape/Plugin.cs +++ b/AutoEvent/Games/ZombieEscape/Plugin.cs @@ -1,4 +1,4 @@ -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using AutoEvent.Events.Handlers; using CustomPlayerEffects; using MEC; @@ -106,7 +106,7 @@ protected override void CountdownFinished() { Extensions.PlayAudio("Zombie2.ogg", 7, false, Name); - foreach (Player ply in Config.Zombies.GetPlayers()) + foreach (Player ply in Config.Zombies.GetPlayers(true)) { DebugLogger.LogDebug($"{ply.Nickname} chosen as a zombie.", LogLevel.Debug); ply.GiveLoadout(Config.ZombieLoadouts); diff --git a/AutoEvent/Interfaces/IEventMap.cs b/AutoEvent/Interfaces/IEventMap.cs index 84305b6e..d623905d 100644 --- a/AutoEvent/Interfaces/IEventMap.cs +++ b/AutoEvent/Interfaces/IEventMap.cs @@ -10,7 +10,7 @@ // Created Date: 09/06/2023 4:10 PM // ----------------------------------------- -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using UnityEngine; namespace AutoEvent.Interfaces; diff --git a/AutoEvent/Interfaces/IHidden.cs b/AutoEvent/Interfaces/IHidden.cs new file mode 100644 index 00000000..7d17d5dd --- /dev/null +++ b/AutoEvent/Interfaces/IHidden.cs @@ -0,0 +1,9 @@ +namespace AutoEvent.Interfaces; + +/// +/// Makes an event hidden on the event list. +/// +internal interface IHidden +{ + +} \ No newline at end of file diff --git a/AutoEvent/Interfaces/IVote.cs b/AutoEvent/Interfaces/IVote.cs new file mode 100644 index 00000000..02d3406a --- /dev/null +++ b/AutoEvent/Interfaces/IVote.cs @@ -0,0 +1,6 @@ +namespace AutoEvent.Interfaces; + +internal interface IVote +{ + Event NewEvent { get; set; } +} \ No newline at end of file diff --git a/AutoEvent/Interfaces/MapInfo.cs b/AutoEvent/Interfaces/MapInfo.cs index 57f2e167..4d6fc0d2 100644 --- a/AutoEvent/Interfaces/MapInfo.cs +++ b/AutoEvent/Interfaces/MapInfo.cs @@ -11,7 +11,7 @@ // ----------------------------------------- using System.ComponentModel; -using AutoEvent.API.Schematic.Objects; +using MER.Lite.Objects; using UnityEngine; using YamlDotNet.Serialization; diff --git a/AutoEvent/Plugin.cs b/AutoEvent/Plugin.cs index 950887c3..63192b17 100644 --- a/AutoEvent/Plugin.cs +++ b/AutoEvent/Plugin.cs @@ -11,6 +11,7 @@ using GameCore; using MEC; using PluginAPI.Core; +using Powerups; using Event = AutoEvent.Interfaces.Event; using Log = PluginAPI.Core.Log; using Paths = PluginAPI.Helpers.Paths; @@ -24,7 +25,7 @@ namespace AutoEvent #if EXILED public class AutoEvent : Plugin { - public override System.Version Version => new System.Version(9, 1, 10); + public override System.Version Version => new System.Version(9, 2, 0); public override string Name => "AutoEvent"; public override string Author => "Created by KoT0XleB, extended by swd and sky, Co-Maintained by Redforce04"; public static bool IsPlayedGames; @@ -38,7 +39,7 @@ public class AutoEvent [PluginConfig("Configs/translation.yml")] public Translation Translation; #endif - public const bool BetaRelease = true; // todo set beta to false before main release + public const bool BetaRelease = false; // todo set beta to false before main release /// /// The location of the AutoEvent folder for schematics, music, external events and event config / translations. /// @@ -54,7 +55,7 @@ public class AutoEvent public override void OnEnabled() #else [PluginPriority(LoadPriority.Low)] - [PluginEntryPoint("AutoEvent", "9.1.5", "An event manager plugin that allows you to run mini-games.", + [PluginEntryPoint("AutoEvent", "9.2.0", "An event manager plugin that allows you to run mini-games.", "KoT0XleB and Redforce04")] void OnEnabled() #endif @@ -85,6 +86,9 @@ private void _startup() try { Singleton = this; + MER.Lite.API.Initialize(AutoEvent.Singleton.Config.SchematicsDirectoryPath, Config.Debug); + Powerups.API.Initialize(); + if (Config.IgnoredRoles.Contains(Config.LobbyRole)) { DebugLogger.LogDebug("The Lobby Role is also in ignored roles. This will break the game if not changed. The plugin will remove the lobby role from ignored roles.", LogLevel.Error, true); @@ -116,7 +120,6 @@ private void _startup() EventManager.RegisterEvents(this); SCPSLAudioApi.Startup.SetupDependencies(); - var powerupManager = new PowerupManager(); Servers.RemoteAdmin += eventHandler.OnRemoteAdmin; try { diff --git a/AutoEvent/PowerupApi/API.cs b/AutoEvent/PowerupApi/API.cs new file mode 100644 index 00000000..5c88f577 --- /dev/null +++ b/AutoEvent/PowerupApi/API.cs @@ -0,0 +1,35 @@ +using Powerups; + +namespace Powerups +{ + public static class API + { + /// + /// Initializes necessary dependencies. + /// + /// Should debug logging be enabled. + public static void Initialize(bool debug = false) + { + if (_initialized) + { + return; + } + _initialized = true; + CosturaUtility.Initialize(); + var powerupManager = new PowerupManager(); + Debug = debug; + } + + private static bool _initialized = false; + + /// + /// Controls Debug Logs. If true, the Api will output debug logs. + /// + public static bool Debug { get; set; } = false; + + /// + /// The main instance of the powerup manager. + /// + public static PowerupManager PowerupManager => PowerupManager.Singleton; + } +} \ No newline at end of file diff --git a/AutoEvent/PowerupApi/Components/BaseCollisionDetectorComponent.cs b/AutoEvent/PowerupApi/Components/BaseCollisionDetectorComponent.cs new file mode 100644 index 00000000..83f2e5eb --- /dev/null +++ b/AutoEvent/PowerupApi/Components/BaseCollisionDetectorComponent.cs @@ -0,0 +1,117 @@ +// +// Copyright (c) Redforce04. All rights reserved. +// +// ----------------------------------------- +// Solution: AutoEvent +// Project: AutoEvent +// FileName: BaseCollisionComponent.cs +// Author: Redforce04#4091 +// Revision Date: 10/17/2023 5:33 PM +// Created Date: 10/17/2023 5:33 PM +// ----------------------------------------- + +using PluginAPI.Core; +using UnityEngine; + +namespace Powerups.Components; + +public class BaseCollisionDetectorComponent : MonoBehaviour + { + /// + /// Gets or sets the raycast distance. + /// + public virtual float RaycastDistance { get; set; } = 1; + + /// + /// Gets or sets the time delay (in seconds) before performing raycast collision checks during each update. + /// + public virtual float Delay { get; set; } = 0.1f; + + private float elapsedTime = 0; + + /// + /// Update is called once per frame. + /// + internal virtual void Update() + { + + if(elapsedTime > Delay) + { + // Raycast upwards + RaycastHit hitUp; + if (Physics.Raycast(transform.position, Vector3.up, out hitUp, RaycastDistance)) + { + OnCollisionWithSomething(hitUp.collider.transform.root.gameObject); + } + + // Raycast downwards + RaycastHit hitDown; + if (Physics.Raycast(transform.position, Vector3.down, out hitDown, RaycastDistance)) + { + + OnCollisionWithSomething(hitDown.collider.transform.root.gameObject); + } + + // Raycast forwards + + RaycastHit hitForward; + if (Physics.Raycast(transform.position, transform.forward, out hitForward, RaycastDistance)) + { + OnCollisionWithSomething(hitForward.collider.transform.root.gameObject); + } + + // Raycast backwards + RaycastHit hitBackward; + if (Physics.Raycast(transform.position, -transform.forward, out hitBackward, RaycastDistance)) + { + OnCollisionWithSomething(hitBackward.collider.transform.root.gameObject); + } + + // Raycast to the left + RaycastHit hitLeft; + if (Physics.Raycast(transform.position, -transform.right, out hitLeft, RaycastDistance)) + { + OnCollisionWithSomething(hitLeft.collider.transform.root.gameObject); + } + + // Raycast to the right + RaycastHit hitRight; + if (Physics.Raycast(transform.position, transform.right, out hitRight, RaycastDistance)) + { + OnCollisionWithSomething(hitRight.collider.transform.root.gameObject); + } + + elapsedTime = 0; + } + + elapsedTime += Time.deltaTime; + } + + /// + /// Called when a collision with an object is detected. + /// + /// The GameObject involved in the collision. + public virtual void OnCollisionWithSomething(GameObject gameObject) + { + // This method can be overridden in derived classes to handle collisions. + } + + public bool IsPlayer(GameObject gameObject, out Player? player) + { + if (gameObject == base.gameObject || gameObject.tag != "Player") + { + player = null; + return false; + } + + if(Player.TryGet(gameObject, out player)) + { + return true; + } + else + { + player = null; + return false; + } + } + } \ No newline at end of file diff --git a/AutoEvent/PowerupApi/Components/PlayerCollisionDetectorComponent.cs b/AutoEvent/PowerupApi/Components/PlayerCollisionDetectorComponent.cs new file mode 100644 index 00000000..3cae8304 --- /dev/null +++ b/AutoEvent/PowerupApi/Components/PlayerCollisionDetectorComponent.cs @@ -0,0 +1,71 @@ +// +// Copyright (c) Redforce04. All rights reserved. +// +// ----------------------------------------- +// Solution: AutoEvent +// Project: AutoEvent +// FileName: PlayerCollisionDetectorComponent.cs +// Author: Redforce04#4091 +// Revision Date: 10/17/2023 5:36 PM +// Created Date: 10/17/2023 5:36 PM +// ----------------------------------------- + +using System; +using PluginAPI.Core; +using UnityEngine; + +namespace Powerups.Components; + +public class PlayerCollisionDetectorComponent : BaseCollisionDetectorComponent +{ + public override float RaycastDistance { get; set; } = 1f; + public override float Delay { get; set; } = 2; + public Player? Player { get; private set; } + + public void Init(Player? ply = null) + { + Player = ply; + } + public override void OnCollisionWithSomething(GameObject gameObject) + { + if (!IsPlayer(gameObject, out var player)) + { + return; + } + + PlayerCollision.Invoke(new PlayerCollisionArgs(player, gameObject)); + } + public event Action PlayerCollision; + + public void Disable() + { + Destroy(this); + } +} +public class PlayerCollisionArgs +{ + /// + /// Initializes an instance of + /// + /// The player colliding with the schematic. + public PlayerCollisionArgs(Player ply, GameObject gameObject) + { + Player = ply; + GameObject = gameObject; + } + + /// + /// The player that collided with the component. + /// + public Player Player { get; init; } + + /// + /// The instance of the gameobject which was collided with. + /// + public GameObject GameObject { get; init; } + + /// + /// If the original object was a player, it will be present here. Otherwise it will be null. + /// + public Player? OriginalPlayer { get; init; } +} \ No newline at end of file diff --git a/AutoEvent/PowerupApi/Components/SchematicCollisionComponent.cs b/AutoEvent/PowerupApi/Components/SchematicCollisionComponent.cs new file mode 100644 index 00000000..ae55dc32 --- /dev/null +++ b/AutoEvent/PowerupApi/Components/SchematicCollisionComponent.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) Redforce04. All rights reserved. +// +// ----------------------------------------- +// Solution: AutoEvent +// Project: AutoEvent +// FileName: SchematicCollisionComponent.cs +// Author: Redforce04#4091 +// Revision Date: 10/17/2023 12:53 AM +// Created Date: 10/17/2023 12:53 AM +// ----------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using AdminToys; +using MER.Lite.Objects; +using Mirror; +using PlayerStatsSystem; +using PluginAPI.Core; +using UnityEngine; + +namespace Powerups.Components; + +public class SchematicCollisionComponent : MonoBehaviour +{ + private BoxCollider collider; + private Vector3 ColliderScale; + private SchematicObject schematic; + public void Init(SchematicObject schematicObject, Vector3 colliderScale) + { + schematic = schematicObject; + ColliderScale = colliderScale; + } + private void Start() + { + collider = gameObject.AddComponent(); + collider.isTrigger = true; + collider.size = ColliderScale; + } + + private void OnTriggerStay(Collider other) + { + if (Player.Get(other.gameObject) is not Player ply) + { + return; + } + + SchematicCollision?.Invoke(new SchematicCollisionArgs(ply, this.gameObject, schematic)); + } + public event Action SchematicCollision; +} + +public class SchematicCollisionArgs +{ + /// + /// Initializes an instance of + /// + /// The player colliding with the schematic. + public SchematicCollisionArgs(Player ply, GameObject gameObject, SchematicObject schematic) + { + Player = ply; + GameObject = gameObject; + Schematic = schematic; + } + + /// + /// The player that collided with the component. + /// + public Player Player { get; init; } + + /// + /// The instance of the gameobject which was collided with. + /// + public GameObject GameObject { get; init; } + + /// + /// The instance of the Schematic which was collided with. + /// + public SchematicObject Schematic { get; init; } +} \ No newline at end of file diff --git a/AutoEvent/PowerupApi/Components/SpinningItemComponent.cs b/AutoEvent/PowerupApi/Components/SpinningItemComponent.cs new file mode 100644 index 00000000..51febdb8 --- /dev/null +++ b/AutoEvent/PowerupApi/Components/SpinningItemComponent.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) Redforce04. All rights reserved. +// +// ----------------------------------------- +// Solution: AutoEvent +// Project: AutoEvent +// FileName: PowerupItem.cs +// Author: Redforce04#4091 +// Revision Date: 10/17/2023 12:40 AM +// Created Date: 10/17/2023 12:40 AM +// ----------------------------------------- + +using UnityEngine; + +namespace Powerups.Components; + using UnityEngine; + + /// + /// Handles rotating a pickup indicator. + /// + public class SpinningItemComponent : MonoBehaviour + { + /// + /// The spinning speed. + /// + public float Speed = 100f; + + /// + private void Update() + { + transform.Rotate(Vector3.up, Time.deltaTime * Speed); + } + } \ No newline at end of file diff --git a/AutoEvent/Powerups/AmmoPowerup.cs b/AutoEvent/PowerupApi/Default/AmmoPowerup.cs similarity index 95% rename from AutoEvent/Powerups/AmmoPowerup.cs rename to AutoEvent/PowerupApi/Default/AmmoPowerup.cs index 9e20f131..006b0e21 100644 --- a/AutoEvent/Powerups/AmmoPowerup.cs +++ b/AutoEvent/PowerupApi/Default/AmmoPowerup.cs @@ -11,14 +11,12 @@ // ----------------------------------------- using System.Collections.Generic; -using AutoEvent.Commands.Debug; -using AutoEvent.Interfaces; using CustomPlayerEffects; using Exiled.API.Features.Items; using PluginAPI.Core; using UnityEngine; -namespace AutoEvent; +namespace Powerups.Default; public class AmmoPowerup : Powerup { diff --git a/AutoEvent/Powerups/SpeedPowerup.cs b/AutoEvent/PowerupApi/Default/SpeedPowerup.cs similarity index 96% rename from AutoEvent/Powerups/SpeedPowerup.cs rename to AutoEvent/PowerupApi/Default/SpeedPowerup.cs index 1d2b0594..5f09fd7a 100644 --- a/AutoEvent/Powerups/SpeedPowerup.cs +++ b/AutoEvent/PowerupApi/Default/SpeedPowerup.cs @@ -10,14 +10,13 @@ // Created Date: 10/17/2023 12:55 PM // ----------------------------------------- -using AutoEvent.API; -using AutoEvent.Interfaces; using CustomPlayerEffects; using InventorySystem.Items.Usables.Scp244.Hypothermia; using PluginAPI.Core; +using Powerups.Extensions; using UnityEngine; -namespace AutoEvent; +namespace Powerups.Default; public sealed class SpeedPowerup : Powerup { diff --git a/AutoEvent/Powerups/TestPowerup.cs b/AutoEvent/PowerupApi/Default/TestPowerup.cs similarity index 80% rename from AutoEvent/Powerups/TestPowerup.cs rename to AutoEvent/PowerupApi/Default/TestPowerup.cs index e0d3a172..258028ed 100644 --- a/AutoEvent/Powerups/TestPowerup.cs +++ b/AutoEvent/PowerupApi/Default/TestPowerup.cs @@ -9,15 +9,11 @@ // Revision Date: 10/17/2023 1:32 AM // Created Date: 10/17/2023 1:32 AM // ----------------------------------------- - -using AutoEvent.API.Components; -using AutoEvent.API.Schematic.Objects; -using AutoEvent.Interfaces; using CustomPlayerEffects; using PluginAPI.Core; using UnityEngine; -namespace AutoEvent; +namespace Powerups.Default; public class TestPowerup : Powerup { @@ -27,14 +23,12 @@ public class TestPowerup : Powerup public override float PowerupDuration { get; protected set; } = 60; protected override void OnApplyPowerup(Player ply) { - DebugLogger.LogDebug($"Applying Powerup {this.Name} to player {ply.Nickname}."); ply.EffectsManager.DisableEffect(); ply.EffectsManager.DisableEffect(); } protected override void OnRemovePowerup(Player ply) { - DebugLogger.LogDebug($"Removing powerup {this.Name} from player {ply.Nickname}."); ply.EffectsManager.EnableEffect(0f, false); ply.EffectsManager.EnableEffect(0f, false).Intensity = 30; } diff --git a/AutoEvent/PowerupApi/Extensions/AbstractTypeExtensions.cs b/AutoEvent/PowerupApi/Extensions/AbstractTypeExtensions.cs new file mode 100644 index 00000000..25b89b86 --- /dev/null +++ b/AutoEvent/PowerupApi/Extensions/AbstractTypeExtensions.cs @@ -0,0 +1,65 @@ +// +// Copyright (c) Redforce04. All rights reserved. +// +// ----------------------------------------- +// Solution: AutoEvent +// Project: AutoEvent +// FileName: AbstractTypeExtensions.cs +// Author: Redforce04#4091 +// Revision Date: 10/17/2023 1:30 AM +// Created Date: 10/17/2023 1:30 AM +// ----------------------------------------- + +namespace Powerups.Extensions; + +using System; +using System.Collections.Generic; +using System.Reflection; + +public static class AbstractedTypeExtensions +{ + /// + /// Every instance of the type found in any loaded assembly will be instantiated and returned into list form. + /// + /// The type to instantiate instances of. + /// A list of all found instances of . + public static List InstantiateAllInstancesOfType() + where T : class + { + Type type = typeof(T); + List instanceList = new List(); + + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + try + { + foreach (Type typeInstance in HarmonyLib.AccessTools.GetTypesFromAssembly(assembly)) + { + if (typeInstance.IsAbstract || typeInstance.IsInterface) + continue; + + if (!typeInstance.IsSubclassOf(type)) + continue; + + try + { + if (Activator.CreateInstance(typeInstance) is not T instance) + continue; + + instanceList.Add(instance); + } + catch + { + // + } + } + } + catch + { + // + } + } + + return instanceList; + } +} \ No newline at end of file diff --git a/AutoEvent/PowerupApi/Extensions/MirrorExtensions.cs b/AutoEvent/PowerupApi/Extensions/MirrorExtensions.cs new file mode 100644 index 00000000..375620e1 --- /dev/null +++ b/AutoEvent/PowerupApi/Extensions/MirrorExtensions.cs @@ -0,0 +1,590 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +using CustomPlayerEffects; +using NorthwoodLib.Pools; +using PluginAPI.Core; + +namespace Powerups.Extensions; + + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Linq; + using System.Reflection; + using System.Reflection.Emit; + using System.Text; + + using InventorySystem.Items.Firearms; + + using Mirror; + + using PlayerRoles; + using PlayerRoles.FirstPersonControl; + using PlayerRoles.PlayableScps.Scp049.Zombies; + using RelativePositioning; + + using Respawning; + + using UnityEngine; + + /// + /// A set of extensions for Networking. + /// + public static class MirrorExtensions + { + private static readonly Dictionary WriterExtensionsValue = new(); + private static readonly Dictionary SyncVarDirtyBitsValue = new(); + private static readonly Dictionary RpcFullNamesValue = new(); + + private static readonly ReadOnlyDictionary ReadOnlyWriterExtensionsValue = + new(WriterExtensionsValue); + + private static readonly ReadOnlyDictionary ReadOnlySyncVarDirtyBitsValue = + new(SyncVarDirtyBitsValue); + + private static readonly ReadOnlyDictionary ReadOnlyRpcFullNamesValue = new(RpcFullNamesValue); + private static MethodInfo setDirtyBitsMethodInfoValue; + private static MethodInfo sendSpawnMessageMethodInfoValue; + private static MethodInfo bufferRpcMethodInfoValue; + + /// + /// Gets corresponding to . + /// + public static ReadOnlyDictionary WriterExtensions + { + get + { + if (WriterExtensionsValue.Count == 0) + { + foreach (MethodInfo method in typeof(NetworkWriterExtensions).GetMethods() + .Where(x => !x.IsGenericMethod && (x.GetParameters()?.Length == 2))) + WriterExtensionsValue.Add( + method.GetParameters().First(x => x.ParameterType != typeof(NetworkWriter)).ParameterType, + method); + + Type fuckNorthwood = + Assembly.GetAssembly(typeof(RoleTypeId)).GetType("Mirror.GeneratedNetworkCode"); + foreach (MethodInfo method in fuckNorthwood.GetMethods().Where(x => + !x.IsGenericMethod && (x.GetParameters()?.Length == 2) && + (x.ReturnType == typeof(void)))) + WriterExtensionsValue.Add( + method.GetParameters().First(x => x.ParameterType != typeof(NetworkWriter)).ParameterType, + method); + + foreach (Type serializer in typeof(ServerConsole).Assembly.GetTypes() + .Where(x => x.Name.EndsWith("Serializer"))) + { + foreach (MethodInfo method in serializer.GetMethods() + .Where(x => (x.ReturnType == typeof(void)) && x.Name.StartsWith("Write"))) + WriterExtensionsValue.Add( + method.GetParameters().First(x => x.ParameterType != typeof(NetworkWriter)) + .ParameterType, method); + } + } + + return ReadOnlyWriterExtensionsValue; + } + } + + /// + /// Gets a all DirtyBit from (format:classname.methodname). + /// + public static ReadOnlyDictionary SyncVarDirtyBits + { + get + { + if (SyncVarDirtyBitsValue.Count == 0) + { + foreach (PropertyInfo property in typeof(ServerConsole).Assembly.GetTypes() + .SelectMany(x => x.GetProperties()) + .Where(m => m.Name.StartsWith("Network"))) + { + MethodInfo setMethod = property.GetSetMethod(); + + if (setMethod is null) + continue; + + MethodBody methodBody = setMethod.GetMethodBody(); + + if (methodBody is null) + continue; + + byte[] bytecodes = methodBody.GetILAsByteArray(); + + if (!SyncVarDirtyBitsValue.ContainsKey($"{property.ReflectedType.Name}.{property.Name}")) + SyncVarDirtyBitsValue.Add($"{property.ReflectedType.Name}.{property.Name}", + bytecodes[bytecodes.LastIndexOf((byte)OpCodes.Ldc_I8.Value) + 1]); + } + } + + return ReadOnlySyncVarDirtyBitsValue; + } + } + + /// + /// Gets Rpc's FullName corresponding to (format:classname.methodname). + /// + public static ReadOnlyDictionary RpcFullNames + { + get + { + if (RpcFullNamesValue.Count == 0) + { + foreach (MethodInfo method in typeof(ServerConsole).Assembly.GetTypes() + .SelectMany(x => + x.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) + .Where(m => m.GetCustomAttributes(typeof(ClientRpcAttribute), false).Length > 0 || + m.GetCustomAttributes(typeof(TargetRpcAttribute), false).Length > 0)) + { + MethodBody methodBody = method.GetMethodBody(); + + if (methodBody is null) + continue; + + byte[] bytecodes = methodBody.GetILAsByteArray(); + + if (!RpcFullNamesValue.ContainsKey($"{method.ReflectedType.Name}.{method.Name}")) + RpcFullNamesValue.Add($"{method.ReflectedType.Name}.{method.Name}", + method.Module.ResolveString(BitConverter.ToInt32(bytecodes, + bytecodes.IndexOf((byte)OpCodes.Ldstr.Value) + 1))); + } + } + + return ReadOnlyRpcFullNamesValue; + } + } + + /// + /// Gets a 's . + /// + public static MethodInfo SetDirtyBitsMethodInfo => setDirtyBitsMethodInfoValue ??= + typeof(NetworkBehaviour).GetMethod(nameof(NetworkBehaviour.SetSyncVarDirtyBit)); + + /// + /// Gets a NetworkServer.SendSpawnMessage's . + /// + public static MethodInfo SendSpawnMessageMethodInfo => sendSpawnMessageMethodInfoValue ??= + typeof(NetworkServer).GetMethod("SendSpawnMessage", BindingFlags.NonPublic | BindingFlags.Static); + + /// + /// Gets a NetworkConnectionToClient.BufferRpc's . + /// + public static MethodInfo BufferRpcMethodInfo => bufferRpcMethodInfoValue ??= + typeof(NetworkConnectionToClient).GetMethod("BufferRpc", BindingFlags.NonPublic | BindingFlags.Instance, + null, CallingConventions.HasThis, new Type[] { typeof(RpcMessage), typeof(int) }, null); + + /// + /// Plays a beep sound that only the target can hear. + /// + /// Target to play sound to. + public static void PlayBeepSound(this Player player) => SendFakeTargetRpc(player, + ReferenceHub.HostHub.networkIdentity, typeof(AmbientSoundPlayer), nameof(AmbientSoundPlayer.RpcPlaySound), + 7); + + /// + /// Set on the player that only the can see. + /// + /// Only this player can see info. + /// Target to set info. + /// Setting info. + public static void SetPlayerInfoForTargetOnly(this Player player, Player target, string info) => + player.SendFakeSyncVar(target.ReferenceHub.networkIdentity, typeof(NicknameSync), + nameof(NicknameSync.Network_customPlayerInfoString), info); + + /// + /// Plays a gun sound that only the can hear. + /// + /// Target to play. + /// Position to play on. + /// Weapon' sound to play. + /// Sound's volume to set. + /// GunAudioMessage's audioClipId to set (default = 0). + public static void PlayGunSound(this Player player, Vector3 position, ItemType itemType, byte volume, + byte audioClipId = 0) + { + GunAudioMessage message = new() + { + Weapon = itemType, + AudioClipId = audioClipId, + MaxDistance = volume, + ShooterHub = player.ReferenceHub, + ShooterPosition = new RelativePosition(position), + }; + + player.Connection.Send(message); + } + + /*/// + /// Sets of a that only the player can see. + /// + /// Room to modify. + /// Only this player can see room color. + /// Color to set. + public static void SetRoomColorForTargetOnly(this Room room, Player target, Color color) + { + target.SendFakeSyncVar(room.RoomLightControllerNetIdentity, typeof(RoomLightController), + nameof(RoomLightController.NetworkOverrideColor), color); + target.SendFakeSyncVar(room.RoomLightControllerNetIdentity, typeof(RoomLightController), + nameof(RoomLightController.NetworkOverrideColor), true); + }*/ + + /// + /// Sets of a that only the player can see. + /// + /// Only this player can see the name changed. + /// Player that will desync the CustomName. + /// Nickname to set. + public static void SetName(this Player target, Player player, string name) + { + target.SendFakeSyncVar(player.Connection.identity, typeof(NicknameSync), + nameof(NicknameSync.Network_displayName), name); + } + + /*/// + /// Sets of a that only the player can see. + /// + /// Room to modify. + /// Only this player can see room color. + /// Light intensity multiplier to set. + public static void SetRoomLightIntensityForTargetOnly(this Room room, Player target, float multiplier) + { + }*/ + + /// + /// Change character model for appearance. + /// It will continue until 's changes. + /// + /// Player to change. + /// Model type. + /// Whether or not to skip the little jump that works around an invisibility issue. + /// The UnitNameId to use for the player's new role, if the player's new role uses unit names. (is NTF). + public static void + ChangeAppearance(this Player player, RoleTypeId type, bool skipJump = false, byte unitId = 0) => + ChangeAppearance(player, type, Player.GetPlayers().Where(x => x != player), skipJump, unitId); + + /// + /// Change character model for appearance. + /// It will continue until 's changes. + /// + /// Player to change. + /// Model type. + /// The players who should see the changed appearance. + /// Whether or not to skip the little jump that works around an invisibility issue. + /// The UnitNameId to use for the player's new role, if the player's new role uses unit names. (is NTF). + public static void ChangeAppearance(this Player player, RoleTypeId type, IEnumerable playersToAffect, + bool skipJump = false, byte unitId = 0) + { + + if (player.RoleBase is not PlayerRoleBase roleBase) + return; + + bool isRisky = type.GetTeam() is Team.Dead || !player.IsAlive; + + NetworkWriterPooled writer = NetworkWriterPool.Get(); + writer.WriteUShort(38952); + writer.WriteUInt(player.NetworkId); + writer.WriteRoleType(type); + + if (roleBase is HumanRole humanRole && humanRole.UsesUnitNames) + { + if (player.RoleBase is not HumanRole) + isRisky = true; + writer.WriteByte(unitId); + } + + if (roleBase is FpcStandardRoleBase fpc) + { + if (player.RoleBase is not FpcStandardRoleBase playerfpc) + isRisky = true; + else + fpc = playerfpc; + + fpc.FpcModule.MouseLook.GetSyncValues(0, out ushort value, out ushort _); + var relativePos = player.RoleBase is IFpcRole fpcRole ? fpcRole.FpcModule.Motor.ReceivedPosition : default; + writer.WriteRelativePosition(relativePos); + + writer.WriteUShort(value); + } + + if (roleBase is ZombieRole) + { + if (player.RoleBase is not ZombieRole) + isRisky = true; + + writer.WriteUShort((ushort)Mathf.Clamp(Mathf.CeilToInt(player.MaxHealth), ushort.MinValue, + ushort.MaxValue)); + } + + foreach (Player target in playersToAffect) + { + if (target != player || !isRisky) + target.Connection.Send(writer.ToArraySegment()); + else + Log.Error($"Prevent Seld-Desync of {player.Nickname} with {type}"); + } + + NetworkWriterPool.Return(writer); + + // To counter a bug that makes the player invisible until they move after changing their appearance, we will teleport them upwards slightly to force a new position update for all clients. + if (!skipJump) + player.Position += Vector3.up * 0.25f; + } + + /// + /// Send CASSIE announcement that only can hear. + /// + /// Target to send. + /// Announcement words. + /// Same on 's isHeld. + /// Same on 's isNoisy. + /// Same on 's isSubtitles. + public static void PlayCassieAnnouncement(this Player player, string words, bool makeHold = false, + bool makeNoise = true, bool isSubtitles = false) + { + foreach (RespawnEffectsController controller in RespawnEffectsController.AllControllers) + { + if (controller != null) + { + SendFakeTargetRpc(player, controller.netIdentity, typeof(RespawnEffectsController), + nameof(RespawnEffectsController.RpcCassieAnnouncement), words, makeHold, makeNoise, + isSubtitles); + } + } + } + + public static void ApplyFakeEffect(this Player player, byte intensity) where T : StatusEffectBase + { + T effect; + if (!player.ReferenceHub.playerEffectsController.TryGetEffect(out effect)) + return; + ApplyFakeEffect(player, effect, intensity); + } + /// + /// Applies a status effect to a player on the client side. Only the player will notice the effect. + /// + /// The player to apply the effect to. + /// The effect to apply. + public static void ApplyFakeEffect(this Player player, StatusEffectBase effect, byte intensity) + { + for (int i = 0; i < player.ReferenceHub.playerEffectsController.EffectsLength; i++) + { + StatusEffectBase statusEffectBase = player.ReferenceHub.playerEffectsController.AllEffects[i]; + if (statusEffectBase == effect) + { + player.ReferenceHub.playerEffectsController._syncEffectsIntensity[i] = intensity; + return; + } + } + } + /// + /// Send CASSIE announcement with custom subtitles for translation that only can hear and see it. + /// + /// Target to send. + /// The message to be reproduced. + /// The translation should be show in the subtitles. + /// Same on 's isHeld. + /// Same on 's isNoisy. + /// Same on 's isSubtitles. + public static void MessageTranslated(this Player player, string words, string translation, + bool makeHold = false, bool makeNoise = true, bool isSubtitles = true) + { + StringBuilder announcement = StringBuilderPool.Shared.Rent(); + + string[] cassies = words.Split('\n'); + string[] translations = translation.Split('\n'); + + for (int i = 0; i < cassies.Length; i++) + announcement.Append($"{translations[i]} {cassies[i].Replace(' ', ' ')} "); + + string message = StringBuilderPool.Shared.ToStringReturn(announcement); + + foreach (RespawnEffectsController controller in RespawnEffectsController.AllControllers) + { + if (controller != null) + { + SendFakeTargetRpc(player, controller.netIdentity, typeof(RespawnEffectsController), + nameof(RespawnEffectsController.RpcCassieAnnouncement), message, makeHold, makeNoise, + isSubtitles); + } + } + } + + /// + /// Send fake values to client's . + /// + /// Target to send. + /// of object that owns . + /// 's type. + /// Property name starting with Network. + /// Value of send to target. + public static void SendFakeSyncVar(this Player target, NetworkIdentity behaviorOwner, Type targetType, + string propertyName, object value) + { + NetworkWriterPooled writer = NetworkWriterPool.Get(); + NetworkWriterPooled writer2 = NetworkWriterPool.Get(); + MakeCustomSyncWriter(behaviorOwner, targetType, null, CustomSyncVarGenerator, writer, writer2); + target.Connection.Send(new EntityStateMessage + { + netId = behaviorOwner.netId, + payload = writer.ToArraySegment(), + }); + + NetworkWriterPool.Return(writer); + NetworkWriterPool.Return(writer2); + + void CustomSyncVarGenerator(NetworkWriter targetWriter) + { + targetWriter.WriteULong(SyncVarDirtyBits[$"{targetType.Name}.{propertyName}"]); + WriterExtensions[value.GetType()]?.Invoke(null, new object[2] { targetWriter, value }); + } + } + + /// + /// Force resync to client's . + /// + /// of object that owns . + /// 's type. + /// Property name starting with Network. + public static void ResyncSyncVar(NetworkIdentity behaviorOwner, Type targetType, string propertyName) => + SetDirtyBitsMethodInfo.Invoke(behaviorOwner.gameObject.GetComponent(targetType), + new object[] { SyncVarDirtyBits[$"{targetType.Name}.{propertyName}"] }); + + /// + /// Send fake values to client's . + /// + /// Target to send. + /// of object that owns . + /// 's type. + /// Property name starting with Rpc. + /// Values of send to target. + public static void SendFakeTargetRpc(Player target, NetworkIdentity behaviorOwner, Type targetType, + string rpcName, params object[] values) + { + NetworkWriterPooled writer = NetworkWriterPool.Get(); + + foreach (object value in values) + WriterExtensions[value.GetType()].Invoke(null, new[] { writer, value }); + + RpcMessage msg = new() + { + netId = behaviorOwner.netId, + componentIndex = (byte)GetComponentIndex(behaviorOwner, targetType), + functionHash = (ushort)RpcFullNames[$"{targetType.Name}.{rpcName}"].GetStableHashCode(), + payload = writer.ToArraySegment(), + }; + + BufferRpcMethodInfo.Invoke(target.Connection, new object[] { msg, 0 }); + + NetworkWriterPool.Return(writer); + } + + /// + /// Send fake values to client's . + /// + /// Target to send. + /// of object that owns . + /// 's type. + /// Custom writing action. + /// + /// EffectOnlySCP207. + /// + /// MirrorExtensions.SendCustomSync(player, player.ReferenceHub.networkIdentity, typeof(PlayerEffectsController), (writer) => { + /// writer.WriteUInt64(1ul); // DirtyObjectsBit + /// writer.WriteUInt32(1); // DirtyIndexCount + /// writer.WriteByte((byte)SyncList<byte>.Operation.OP_SET); // Operations + /// writer.WriteUInt32(17); // EditIndex + /// writer.WriteByte(1); // Value + /// }); + /// + /// + public static void SendFakeSyncObject(Player target, NetworkIdentity behaviorOwner, Type targetType, + Action customAction) + { + NetworkWriterPooled writer = NetworkWriterPool.Get(); + NetworkWriterPooled writer2 = NetworkWriterPool.Get(); + MakeCustomSyncWriter(behaviorOwner, targetType, customAction, null, writer, writer2); + target.ReferenceHub.networkIdentity.connectionToClient.Send(new EntityStateMessage() + { netId = behaviorOwner.netId, payload = writer.ToArraySegment() }); + NetworkWriterPool.Return(writer); + NetworkWriterPool.Return(writer2); + } + + /// + /// Edit 's parameter and sync. + /// + /// Target object. + /// Edit function. + public static void EditNetworkObject(NetworkIdentity identity, Action customAction) + { + customAction.Invoke(identity); + + ObjectDestroyMessage objectDestroyMessage = new() + { + netId = identity.netId, + }; + + foreach (Player player in Player.GetPlayers()) + { + player.Connection.Send(objectDestroyMessage, 0); + SendSpawnMessageMethodInfo.Invoke(null, new object[] { identity, player.Connection }); + } + } + + // Get components index in identity.(private) + private static int GetComponentIndex(NetworkIdentity identity, Type type) + { + return Array.FindIndex(identity.NetworkBehaviours, (x) => x.GetType() == type); + } + + // Make custom writer(private) + private static void MakeCustomSyncWriter(NetworkIdentity behaviorOwner, Type targetType, + Action customSyncObject, Action customSyncVar, NetworkWriter owner, + NetworkWriter observer) + { + ulong value = 0; + NetworkBehaviour behaviour = null; + + // Get NetworkBehaviors index (behaviorDirty use index) + for (int i = 0; i < behaviorOwner.NetworkBehaviours.Length; i++) + { + if (behaviorOwner.NetworkBehaviours[i].GetType() == targetType) + { + behaviour = behaviorOwner.NetworkBehaviours[i]; + value = 1UL << (i & 31); + break; + } + } + + // Write target NetworkBehavior's dirty + Compression.CompressVarUInt(owner, value); + + // Write init position + int position = owner.Position; + owner.WriteByte(0); + int position2 = owner.Position; + + // Write custom sync data + if (customSyncObject is not null) + customSyncObject(owner); + else + behaviour.SerializeObjectsDelta(owner); + + // Write custom syncvar + customSyncVar?.Invoke(owner); + + // Write syncdata position data + int position3 = owner.Position; + owner.Position = position; + owner.WriteByte((byte)(position3 - position2 & 255)); + owner.Position = position3; + + // Copy owner to observer + if (behaviour.syncMode != SyncMode.Observers) + observer.WriteBytes(owner.ToArraySegment().Array, position, owner.Position - position); + } + } \ No newline at end of file diff --git a/AutoEvent/PowerupApi/FodyWeavers.xml b/AutoEvent/PowerupApi/FodyWeavers.xml new file mode 100644 index 00000000..5c41350f --- /dev/null +++ b/AutoEvent/PowerupApi/FodyWeavers.xml @@ -0,0 +1,12 @@ + + + + Newtonsoft.Json + 0Harmony + System.ComponentModel.DataAnnotations + YamlDotNet + SchematicApi + + + + \ No newline at end of file diff --git a/AutoEvent/PowerupApi/FodyWeavers.xsd b/AutoEvent/PowerupApi/FodyWeavers.xsd new file mode 100644 index 00000000..05e92c11 --- /dev/null +++ b/AutoEvent/PowerupApi/FodyWeavers.xsd @@ -0,0 +1,141 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Controls if runtime assemblies are also embedded. + + + + + Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/AutoEvent/Interfaces/Powerup.cs b/AutoEvent/PowerupApi/Powerup.cs similarity index 56% rename from AutoEvent/Interfaces/Powerup.cs rename to AutoEvent/PowerupApi/Powerup.cs index 789c3d88..9250e063 100644 --- a/AutoEvent/Interfaces/Powerup.cs +++ b/AutoEvent/PowerupApi/Powerup.cs @@ -11,34 +11,67 @@ // ----------------------------------------- using System.Collections.Generic; -using AdminToys; -using AutoEvent.API.Components; -using AutoEvent.API.Schematic; -using AutoEvent.API.Schematic.Objects; -using CedMod.Addons.AdminSitSystem.Commands.Jail; -using MEC; -using Mirror; +using MER.Lite; +using MER.Lite.Objects; using PluginAPI.Core; +using Powerups.Components; using UnityEngine; -namespace AutoEvent.Interfaces; +namespace Powerups; +/// +/// The abstract implementation used to define powerups. +/// public abstract class Powerup { + /// + /// Initializes a new . + /// public Powerup() { ActivePlayers = new Dictionary(); Schematics = new List(); } + + /// + /// The name of the . If another is found by the same name, it will become "name-1" + /// public abstract string Name { get; protected set; } + + /// + /// A description of the powerup. + /// public abstract string Description { get; protected set; } - public virtual float PowerupDuration { get; protected set; } = float.MaxValue; + + /// + /// How long the should last. Set to -1 to disable the duration system (Non-Reversible Powerups). + /// + public virtual float PowerupDuration { get; protected set; } = -1; + + /// + /// The name of the schematic to spawn for the . + /// protected virtual string SchematicName { get; set; } + + /// + /// The scale of the . This makes the bigger or smaller when spawned. + /// protected virtual Vector3 SchematicScale { get; set; } = Vector3.one; + + /// + /// The Scale of the . This most likely won't scale the same as the , so use this to make the collider bigger / smaller. + /// protected virtual Vector3 ColliderScale { get; set; } = Vector3.one; + + /// + /// A list of all that give this . + /// protected List Schematics { get; set; } - internal Dictionary ActivePlayers { get; set; } + /// + /// A list of Players that have this effect active. This can be disabled by setting the to a negative amount. + /// + public Dictionary ActivePlayers { get; internal set; } /// /// Called when a player collides with the object. @@ -60,17 +93,20 @@ public virtual void SpawnPickup(Vector3 position, float scaleModifer = 1f, float { // Load the schematic of the powerup. - DebugLogger.LogDebug($"Spawning Powerup {this.Name} at ({position.x}, {position.y}, {position.z}), ({SchematicScale.x * scaleModifer}x{SchematicScale.y* scaleModifer}x{SchematicScale.z* scaleModifer})"); + if(API.Debug) + Log.Debug($"Spawning Powerup {this.Name} at ({position.x}, {position.y}, {position.z}), ({SchematicScale.x * scaleModifer}x{SchematicScale.y* scaleModifer}x{SchematicScale.z* scaleModifer})"); var schematic = ObjectSpawner.SpawnSchematic(this.SchematicName, position, Quaternion.Euler(Vector3.zero), this.SchematicScale* scaleModifer); if (schematic is null) { - DebugLogger.LogDebug($"Schematic is null. Cannot spawn pickup."); + if(API.Debug) + Log.Debug($"Schematic is null. Cannot spawn pickup."); return; } if (schematic.gameObject is null) { - DebugLogger.LogDebug($"Schematic Gameobject is null. Cannot spawn pickup."); + if(API.Debug) + Log.Debug($"Schematic Gameobject is null. Cannot spawn pickup."); return; } @@ -81,11 +117,18 @@ public virtual void SpawnPickup(Vector3 position, float scaleModifer = 1f, float collisionComponent.Init(schematic, ColliderScale * colliderScaleModifier); Schematics.Add(schematic); - DebugLogger.LogDebug($"Schematic position ({schematic.Position.z}, {schematic.Position.y}, {schematic.Position.z})."); + if(API.Debug) + Log.Debug($"Schematic position ({schematic.Position.z}, {schematic.Position.y}, {schematic.Position.z})."); } + /// + /// Use this to apply this to a player. + /// + /// The to apply the to. public void ApplyPowerup(Player ply) { + if (PowerupDuration < 0) + goto OnApplyPowerup; if (!ActivePlayers.ContainsKey(ply)) { ActivePlayers.Add(ply, this.PowerupDuration); @@ -94,11 +137,12 @@ public void ApplyPowerup(Player ply) { ActivePlayers[ply] = this.PowerupDuration; } + OnApplyPowerup: OnApplyPowerup(ply); } /// - /// Used to apply a Powerup to a player. + /// Used to apply a to a player. /// /// The player to apply it to. protected virtual void OnApplyPowerup(Player ply) @@ -115,6 +159,11 @@ public virtual void ExpirePowerup(Player ply) RemovePowerup(ply); } + + /// + /// Used to remove a from the effects of the . Not all Powerups can be removed (Ammo). + /// + /// The to remove the powerup from. public void RemovePowerup(Player ply) { if (ActivePlayers.ContainsKey(ply)) @@ -133,6 +182,11 @@ protected virtual void OnRemovePowerup(Player ply) } + /// + /// Checks if a has this effect active. Some powerups don't track this, and only apply the powerup once. (Ammo) + /// + /// The to check. + /// public virtual bool PlayerHasEffect(Player ply) { return this.ActivePlayers.ContainsKey(ply); diff --git a/AutoEvent/PowerupApi/PowerupApi.csproj b/AutoEvent/PowerupApi/PowerupApi.csproj new file mode 100644 index 00000000..47c05f17 --- /dev/null +++ b/AutoEvent/PowerupApi/PowerupApi.csproj @@ -0,0 +1,69 @@ + + + net48 + latest + SLPowerups + SLPowerups + Copyright RisottoMan and Redforce04 © 2023 + bin\$(Configuration)\ + enable + Release + AnyCPU + Powerups + + + ..\bin\Release\NWApi + TRACE + true + true + x64 + v4.8 + 512 + true + default + + + + true + + + + all + runtime; compile; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; compile; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AutoEvent/Powerups/PowerupManager.cs b/AutoEvent/PowerupApi/PowerupManager.cs similarity index 72% rename from AutoEvent/Powerups/PowerupManager.cs rename to AutoEvent/PowerupApi/PowerupManager.cs index e871fd44..bf27ae99 100644 --- a/AutoEvent/Powerups/PowerupManager.cs +++ b/AutoEvent/PowerupApi/PowerupManager.cs @@ -13,15 +13,17 @@ using System; using System.Collections.Generic; using System.Linq; -using AutoEvent.API; -using AutoEvent.Interfaces; using MEC; using PluginAPI.Core; +using Powerups.Extensions; -namespace AutoEvent; - -public class PowerupManager +namespace Powerups; + +public sealed class PowerupManager { + /// + /// The main instance of the powerup manager. You must call or else the singleton will be null. + /// public static PowerupManager Singleton; internal PowerupManager() { @@ -48,10 +50,6 @@ private IEnumerator ProcessPowerups() { while (!KillLoop) { - if (AutoEvent.ActiveEvent == null) - { - goto skip; - } foreach (Powerup powerup in RegisteredPowerups) { @@ -77,13 +75,26 @@ private IEnumerator ProcessPowerups() } } + /// + /// A list of all registered powerups. + /// public static List RegisteredPowerups { get; set; } + /// + /// Gets a by its type. + /// + /// The type of the you are trying to get. + /// The (if it is found) or null. public static T GetPowerup() where T : Powerup { return (T)RegisteredPowerups.First(powerup => powerup is T); } + /// + /// Gets a by its type. + /// + /// The type of the you are trying to get. + /// The (if it is found) or null. public static Powerup? GetPowerup(Type type) { if (type.BaseType != typeof(Powerup)) @@ -94,6 +105,11 @@ public static T GetPowerup() where T : Powerup return RegisteredPowerups.FirstOrDefault(powerup => powerup.GetType() == type); } + /// + /// Gets a by its name. + /// + /// The name of the you are trying to get. + /// The (if it is found) or null. public static Powerup? GetPowerup(string name) { if (string.IsNullOrWhiteSpace(name)) diff --git a/AutoEvent/PowerupApi/Properties/AssemblyInfo.cs b/AutoEvent/PowerupApi/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f7ce16ff --- /dev/null +++ b/AutoEvent/PowerupApi/Properties/AssemblyInfo.cs @@ -0,0 +1,22 @@ +using System.Reflection; +using System.Runtime.InteropServices; + + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1B07FE64-A112-499D-8A55-67EE912B1CB7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] \ No newline at end of file diff --git a/AutoEvent/SchematicApi/API.cs b/AutoEvent/SchematicApi/API.cs new file mode 100644 index 00000000..40080040 --- /dev/null +++ b/AutoEvent/SchematicApi/API.cs @@ -0,0 +1,35 @@ +namespace MER.Lite +{ + public static class API + { + /// + /// Initializes MER Lite + /// + /// The location for the schematic folder. + /// Whether debug logs should be enabled. + public static void Initialize(string schematicLocation, bool debug = false) + { + if (_initialized) + { + return; + } + _initialized = true; + + SchematicLocation = schematicLocation; + Debug = debug; + CosturaUtility.Initialize(); + } + + private static bool _initialized = false; + + /// + /// Controls Debug Logs. If true, the Api will output debug logs. + /// + public static bool Debug { get; set; } + + /// + /// The location of the schematics folder. + /// + public static string SchematicLocation { get; set; } + } +} \ No newline at end of file diff --git a/AutoEvent/API/Schematic/AnimationController.cs b/AutoEvent/SchematicApi/AnimationController.cs similarity index 97% rename from AutoEvent/API/Schematic/AnimationController.cs rename to AutoEvent/SchematicApi/AnimationController.cs index 18fae3c7..aa7bc2c5 100644 --- a/AutoEvent/API/Schematic/AnimationController.cs +++ b/AutoEvent/SchematicApi/AnimationController.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic +namespace MER.Lite { using System.Collections.Generic; using System.Linq; diff --git a/AutoEvent/SchematicApi/Components/PickupComponent.cs b/AutoEvent/SchematicApi/Components/PickupComponent.cs new file mode 100644 index 00000000..098f1d95 --- /dev/null +++ b/AutoEvent/SchematicApi/Components/PickupComponent.cs @@ -0,0 +1,21 @@ +// +// Copyright (c) Redforce04. All rights reserved. +// +// ----------------------------------------- +// Solution: AutoEvent +// Project: SchematicApi +// FileName: PickupComponent.cs +// Author: Redforce04#4091 +// Revision Date: 10/21/2023 8:31 PM +// Created Date: 10/21/2023 8:31 PM +// ----------------------------------------- + + +using UnityEngine; + +namespace MER.Lite.Components; + +public class PickupComponent : Component +{ + // Used to track pickups. +} \ No newline at end of file diff --git a/AutoEvent/API/Schematic/Enums/BlockType.cs b/AutoEvent/SchematicApi/Enums/BlockType.cs similarity index 83% rename from AutoEvent/API/Schematic/Enums/BlockType.cs rename to AutoEvent/SchematicApi/Enums/BlockType.cs index 150a83fa..7744646b 100644 --- a/AutoEvent/API/Schematic/Enums/BlockType.cs +++ b/AutoEvent/SchematicApi/Enums/BlockType.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Enums +namespace MER.Lite.Enums { public enum BlockType { diff --git a/AutoEvent/API/Schematic/Enums/CullingType.cs b/AutoEvent/SchematicApi/Enums/CullingType.cs similarity index 70% rename from AutoEvent/API/Schematic/Enums/CullingType.cs rename to AutoEvent/SchematicApi/Enums/CullingType.cs index 26072479..7a44e395 100644 --- a/AutoEvent/API/Schematic/Enums/CullingType.cs +++ b/AutoEvent/SchematicApi/Enums/CullingType.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Enums +namespace MER.Lite.Enums { public enum CullingType { diff --git a/AutoEvent/API/Schematic/Enums/LockerType.cs b/AutoEvent/SchematicApi/Enums/LockerType.cs similarity index 80% rename from AutoEvent/API/Schematic/Enums/LockerType.cs rename to AutoEvent/SchematicApi/Enums/LockerType.cs index 9d086741..b744e085 100644 --- a/AutoEvent/API/Schematic/Enums/LockerType.cs +++ b/AutoEvent/SchematicApi/Enums/LockerType.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Enums +namespace MER.Lite.Enums { public enum LockerType { diff --git a/AutoEvent/SchematicApi/FodyWeavers.xml b/AutoEvent/SchematicApi/FodyWeavers.xml new file mode 100644 index 00000000..0b56460e --- /dev/null +++ b/AutoEvent/SchematicApi/FodyWeavers.xml @@ -0,0 +1,11 @@ + + + + Newtonsoft.Json + 0Harmony + System.ComponentModel.DataAnnotations + YamlDotNet + + + + \ No newline at end of file diff --git a/AutoEvent/SchematicApi/FodyWeavers.xsd b/AutoEvent/SchematicApi/FodyWeavers.xsd new file mode 100644 index 00000000..05e92c11 --- /dev/null +++ b/AutoEvent/SchematicApi/FodyWeavers.xsd @@ -0,0 +1,141 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Controls if runtime assemblies are also embedded. + + + + + Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/AutoEvent/API/Schematic/MapUtils.cs b/AutoEvent/SchematicApi/MapUtils.cs similarity index 64% rename from AutoEvent/API/Schematic/MapUtils.cs rename to AutoEvent/SchematicApi/MapUtils.cs index f1b7c437..62bdbaf5 100644 --- a/AutoEvent/API/Schematic/MapUtils.cs +++ b/AutoEvent/SchematicApi/MapUtils.cs @@ -1,4 +1,6 @@ -namespace AutoEvent.API.Schematic +using PluginAPI.Core; + +namespace MER.Lite { using System.IO; using PluginAPI.Helpers; @@ -9,14 +11,16 @@ public static class MapUtils { public static SchematicObjectDataList GetSchematicDataByName(string schematicName) { - string dirPath = Path.Combine(AutoEvent.Singleton.Config.SchematicsDirectoryPath, schematicName); + string dirPath = Path.Combine(API.SchematicLocation, schematicName); - DebugLogger.LogDebug($"Path exists: {Directory.Exists(dirPath)}, Directory Path: {dirPath}"); + if(API.Debug) + Log.Debug($"Path exists: {Directory.Exists(dirPath)}, Directory Path: {dirPath}"); if (!Directory.Exists(dirPath)) return null; string schematicPath = Path.Combine(dirPath, $"{schematicName}.json"); - DebugLogger.LogDebug($"File Exists: {File.Exists(schematicPath)}, Schematic Path: {schematicPath}"); + if(API.Debug) + Log.Debug($"File Exists: {File.Exists(schematicPath)}, Schematic Path: {schematicPath}"); if (!File.Exists(schematicPath)) return null; diff --git a/AutoEvent/API/Schematic/ObjectHelper.cs b/AutoEvent/SchematicApi/ObjectHelper.cs similarity index 99% rename from AutoEvent/API/Schematic/ObjectHelper.cs rename to AutoEvent/SchematicApi/ObjectHelper.cs index 87aea59d..a6225dd3 100644 --- a/AutoEvent/API/Schematic/ObjectHelper.cs +++ b/AutoEvent/SchematicApi/ObjectHelper.cs @@ -4,7 +4,7 @@ using Mirror; using UnityEngine; -namespace AutoEvent.API.Schematic +namespace MER.Lite { public static class ObjectHelper { diff --git a/AutoEvent/API/Schematic/ObjectSpawner.cs b/AutoEvent/SchematicApi/ObjectSpawner.cs similarity index 95% rename from AutoEvent/API/Schematic/ObjectSpawner.cs rename to AutoEvent/SchematicApi/ObjectSpawner.cs index 153b73f9..d89555ed 100644 --- a/AutoEvent/API/Schematic/ObjectSpawner.cs +++ b/AutoEvent/SchematicApi/ObjectSpawner.cs @@ -1,10 +1,11 @@ -namespace AutoEvent.API.Schematic +using MER.Lite.Objects; + +namespace MER.Lite { using MapGeneration; using Serializable; using UnityEngine; using System.Linq; - using global::AutoEvent.API.Schematic.Objects; public static class ObjectSpawner { diff --git a/AutoEvent/API/Schematic/Objects/LightSourceObjects.cs b/AutoEvent/SchematicApi/Objects/LightSourceObjects.cs similarity index 97% rename from AutoEvent/API/Schematic/Objects/LightSourceObjects.cs rename to AutoEvent/SchematicApi/Objects/LightSourceObjects.cs index a259ad97..675863d7 100644 --- a/AutoEvent/API/Schematic/Objects/LightSourceObjects.cs +++ b/AutoEvent/SchematicApi/Objects/LightSourceObjects.cs @@ -1,5 +1,5 @@  -namespace AutoEvent.API.Schematic.Objects +namespace MER.Lite.Objects { using AdminToys; using MapGeneration; diff --git a/AutoEvent/API/Schematic/Objects/LockerObject.cs b/AutoEvent/SchematicApi/Objects/LockerObject.cs similarity index 98% rename from AutoEvent/API/Schematic/Objects/LockerObject.cs rename to AutoEvent/SchematicApi/Objects/LockerObject.cs index 9edca9ce..fb8362d9 100644 --- a/AutoEvent/API/Schematic/Objects/LockerObject.cs +++ b/AutoEvent/SchematicApi/Objects/LockerObject.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Objects +namespace MER.Lite.Objects { using System; using System.Collections.Generic; diff --git a/AutoEvent/API/Schematic/Objects/MapEditorObject.cs b/AutoEvent/SchematicApi/Objects/MapEditorObject.cs similarity index 98% rename from AutoEvent/API/Schematic/Objects/MapEditorObject.cs rename to AutoEvent/SchematicApi/Objects/MapEditorObject.cs index 0d0bdd42..29bad1d3 100644 --- a/AutoEvent/API/Schematic/Objects/MapEditorObject.cs +++ b/AutoEvent/SchematicApi/Objects/MapEditorObject.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Objects +namespace MER.Lite.Objects { using System; using System.Linq; diff --git a/AutoEvent/API/Schematic/Objects/PrimitiveObject.cs b/AutoEvent/SchematicApi/Objects/PrimitiveObject.cs similarity index 98% rename from AutoEvent/API/Schematic/Objects/PrimitiveObject.cs rename to AutoEvent/SchematicApi/Objects/PrimitiveObject.cs index 4979002f..a1bcd74e 100644 --- a/AutoEvent/API/Schematic/Objects/PrimitiveObject.cs +++ b/AutoEvent/SchematicApi/Objects/PrimitiveObject.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Objects +namespace MER.Lite.Objects { using AdminToys; using Serializable; diff --git a/AutoEvent/API/Schematic/Objects/SchematicObject.cs b/AutoEvent/SchematicApi/Objects/SchematicObject.cs similarity index 97% rename from AutoEvent/API/Schematic/Objects/SchematicObject.cs rename to AutoEvent/SchematicApi/Objects/SchematicObject.cs index a47058f2..7354b82f 100644 --- a/AutoEvent/API/Schematic/Objects/SchematicObject.cs +++ b/AutoEvent/SchematicApi/Objects/SchematicObject.cs @@ -1,4 +1,6 @@ -namespace AutoEvent.API.Schematic.Objects +using MER.Lite.Components; + +namespace MER.Lite.Objects { using System; using System.Collections.Generic; @@ -23,7 +25,7 @@ public class SchematicObject : MapEditorObject { public SchematicObject Init(SchematicSerializable schematicSerializable, SchematicObjectDataList data) { - DebugLogger.LogDebug($"Initializing schematic \"{schematicSerializable.SchematicName}\"", LogLevel.Info, true); + // Log.Debug($"Initializing schematic \"{schematicSerializable.SchematicName}\""); Base = schematicSerializable; SchematicData = data; @@ -297,7 +299,7 @@ private bool TryGetAnimatorController(string animatorName, out RuntimeAnimatorCo if (!File.Exists(path)) { - DebugLogger.LogDebug($"{gameObject.name} block of {name} should have a {animatorName} animator attached, but the file does not exist!", LogLevel.Warn, true); + Log.Warning($"{gameObject.name} block of {name} should have a {animatorName} animator attached, but the file does not exist!"); return false; } diff --git a/AutoEvent/API/Schematic/Objects/WorkstationObject.cs b/AutoEvent/SchematicApi/Objects/WorkstationObject.cs similarity index 96% rename from AutoEvent/API/Schematic/Objects/WorkstationObject.cs rename to AutoEvent/SchematicApi/Objects/WorkstationObject.cs index c5c82e5d..c023626a 100644 --- a/AutoEvent/API/Schematic/Objects/WorkstationObject.cs +++ b/AutoEvent/SchematicApi/Objects/WorkstationObject.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Objects +namespace MER.Lite.Objects { using InventorySystem.Items.Firearms.Attachments; using MapGeneration.Distributors; diff --git a/AutoEvent/SchematicApi/Properties/AssemblyInfo.cs b/AutoEvent/SchematicApi/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..a7f05f71 --- /dev/null +++ b/AutoEvent/SchematicApi/Properties/AssemblyInfo.cs @@ -0,0 +1,22 @@ +using System.Reflection; +using System.Runtime.InteropServices; + + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("580DFED2-B2D7-4B89-B245-D60246BCFB79")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] \ No newline at end of file diff --git a/AutoEvent/SchematicApi/SchematicApi.csproj b/AutoEvent/SchematicApi/SchematicApi.csproj new file mode 100644 index 00000000..1fe205bc --- /dev/null +++ b/AutoEvent/SchematicApi/SchematicApi.csproj @@ -0,0 +1,68 @@ + + + net48 + latest + MERLite + MERLite + Copyright RisottoMan and Redforce04 © 2023 + bin\$(Configuration)\ + enable + Release + AnyCPU + MER.Lite + + + ..\bin\Release\NWApi + TRACE + true + true + x64 + v4.8 + 512 + true + default + + + + true + bin\Release\SchematicApi.xml + + + + all + runtime; compile; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; compile; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AutoEvent/API/Schematic/Serializable/LightSourcesSerializable.cs b/AutoEvent/SchematicApi/Serializable/LightSourcesSerializable.cs similarity index 95% rename from AutoEvent/API/Schematic/Serializable/LightSourcesSerializable.cs rename to AutoEvent/SchematicApi/Serializable/LightSourcesSerializable.cs index c8e38c3d..77f4cc7f 100644 --- a/AutoEvent/API/Schematic/Serializable/LightSourcesSerializable.cs +++ b/AutoEvent/SchematicApi/Serializable/LightSourcesSerializable.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using System; using UnityEngine; diff --git a/AutoEvent/API/Schematic/Serializable/LockerItemSerializable.cs b/AutoEvent/SchematicApi/Serializable/LockerItemSerializable.cs similarity index 94% rename from AutoEvent/API/Schematic/Serializable/LockerItemSerializable.cs rename to AutoEvent/SchematicApi/Serializable/LockerItemSerializable.cs index 13f429fa..6cb8bb46 100644 --- a/AutoEvent/API/Schematic/Serializable/LockerItemSerializable.cs +++ b/AutoEvent/SchematicApi/Serializable/LockerItemSerializable.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using System.Collections.Generic; using InventorySystem.Items.Firearms.Attachments; diff --git a/AutoEvent/API/Schematic/Serializable/LockerSerializable.cs b/AutoEvent/SchematicApi/Serializable/LockerSerializable.cs similarity index 98% rename from AutoEvent/API/Schematic/Serializable/LockerSerializable.cs rename to AutoEvent/SchematicApi/Serializable/LockerSerializable.cs index ca78275e..0ddd4646 100644 --- a/AutoEvent/API/Schematic/Serializable/LockerSerializable.cs +++ b/AutoEvent/SchematicApi/Serializable/LockerSerializable.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using System; using System.Collections.Generic; diff --git a/AutoEvent/API/Schematic/Serializable/PrimitiveSerializable.cs b/AutoEvent/SchematicApi/Serializable/PrimitiveSerializable.cs similarity index 93% rename from AutoEvent/API/Schematic/Serializable/PrimitiveSerializable.cs rename to AutoEvent/SchematicApi/Serializable/PrimitiveSerializable.cs index 7c62aae9..935e7e0a 100644 --- a/AutoEvent/API/Schematic/Serializable/PrimitiveSerializable.cs +++ b/AutoEvent/SchematicApi/Serializable/PrimitiveSerializable.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using System; using UnityEngine; diff --git a/AutoEvent/API/Schematic/Serializable/SchematicObjectDataList.cs b/AutoEvent/SchematicApi/Serializable/SchematicObjectDataList.cs similarity index 94% rename from AutoEvent/API/Schematic/Serializable/SchematicObjectDataList.cs rename to AutoEvent/SchematicApi/Serializable/SchematicObjectDataList.cs index f4352939..7980a91a 100644 --- a/AutoEvent/API/Schematic/Serializable/SchematicObjectDataList.cs +++ b/AutoEvent/SchematicApi/Serializable/SchematicObjectDataList.cs @@ -1,4 +1,4 @@ -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { #pragma warning disable SA1402 // File may only contain a single type using System; diff --git a/AutoEvent/API/Schematic/Serializable/SchematicSerializable.cs b/AutoEvent/SchematicApi/Serializable/SchematicSerializable.cs similarity index 90% rename from AutoEvent/API/Schematic/Serializable/SchematicSerializable.cs rename to AutoEvent/SchematicApi/Serializable/SchematicSerializable.cs index 38a960fc..ce1feef5 100644 --- a/AutoEvent/API/Schematic/Serializable/SchematicSerializable.cs +++ b/AutoEvent/SchematicApi/Serializable/SchematicSerializable.cs @@ -1,5 +1,5 @@  -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using System; using Enums; diff --git a/AutoEvent/API/Schematic/Serializable/SerializableObject.cs b/AutoEvent/SchematicApi/Serializable/SerializableObject.cs similarity index 88% rename from AutoEvent/API/Schematic/Serializable/SerializableObject.cs rename to AutoEvent/SchematicApi/Serializable/SerializableObject.cs index 87fffa45..b6c92d1b 100644 --- a/AutoEvent/API/Schematic/Serializable/SerializableObject.cs +++ b/AutoEvent/SchematicApi/Serializable/SerializableObject.cs @@ -1,5 +1,5 @@  -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using MapGeneration; using UnityEngine; diff --git a/AutoEvent/API/Schematic/Serializable/SerializableRigidbody.cs b/AutoEvent/SchematicApi/Serializable/SerializableRigidbody.cs similarity index 87% rename from AutoEvent/API/Schematic/Serializable/SerializableRigidbody.cs rename to AutoEvent/SchematicApi/Serializable/SerializableRigidbody.cs index 0db89724..fa0f3387 100644 --- a/AutoEvent/API/Schematic/Serializable/SerializableRigidbody.cs +++ b/AutoEvent/SchematicApi/Serializable/SerializableRigidbody.cs @@ -1,5 +1,5 @@  -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using UnityEngine; diff --git a/AutoEvent/API/Schematic/Serializable/WorkstationSerializable.cs b/AutoEvent/SchematicApi/Serializable/WorkstationSerializable.cs similarity index 93% rename from AutoEvent/API/Schematic/Serializable/WorkstationSerializable.cs rename to AutoEvent/SchematicApi/Serializable/WorkstationSerializable.cs index a4febca6..cd4b3bda 100644 --- a/AutoEvent/API/Schematic/Serializable/WorkstationSerializable.cs +++ b/AutoEvent/SchematicApi/Serializable/WorkstationSerializable.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace AutoEvent.API.Schematic.Serializable +namespace MER.Lite.Serializable { using System; diff --git a/Music/FireSale.ogg b/Music/FireSale.ogg index 7828681d..0e5e97d5 100644 Binary files a/Music/FireSale.ogg and b/Music/FireSale.ogg differ diff --git a/README.md b/README.md index 455a4cbb..35bafc93 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # AutoEvent ## ENG: Allows you to run auto Mini-Games in the game. ## RUS: Позволяет запускать автоматические Мини-Игры в игре. +**Developers:** SchematicApi (MER.Lite) releases can be found [here](https://github.com/Redforce04/SchematicApi). Powerup Api releases can be found [here](https://github.com/Redforce04/PowerupApi). Development for both of these Api's occur on the dev branch of this repo. + ![Logo](https://github.com/KoT0XleB/AutoEvent/blob/main/Photos/MiniGames(mini).png) # Guides: diff --git a/Schematics/Lobby/Lobby.json b/Schematics/Lobby/Lobby.json index d50ff4f8..afb72b80 100644 --- a/Schematics/Lobby/Lobby.json +++ b/Schematics/Lobby/Lobby.json @@ -1,10 +1,10 @@ { - "RootObjectId": -9886, + "RootObjectId": -1190, "Blocks": [ { "Name": "LightSource", - "ObjectId": -9890, - "ParentId": -9886, + "ObjectId": -1932, + "ParentId": -1190, "Position": { "x": 0.0, "y": 12.1, @@ -20,8 +20,8 @@ }, { "Name": "LightSource", - "ObjectId": -9892, - "ParentId": -9886, + "ObjectId": -1934, + "ParentId": -1190, "Position": { "x": 0.03, "y": 6.48, @@ -37,8 +37,8 @@ }, { "Name": "LightSource", - "ObjectId": -9894, - "ParentId": -9886, + "ObjectId": -1936, + "ParentId": -1190, "Position": { "x": 0.0, "y": 12.1, @@ -54,8 +54,8 @@ }, { "Name": "LightSource", - "ObjectId": -9896, - "ParentId": -9886, + "ObjectId": -1938, + "ParentId": -1190, "Position": { "x": 0.0, "y": 12.1, @@ -71,8 +71,8 @@ }, { "Name": "LightSource", - "ObjectId": -9898, - "ParentId": -9886, + "ObjectId": -1940, + "ParentId": -1190, "Position": { "x": -8.58, "y": 12.1, @@ -88,8 +88,8 @@ }, { "Name": "LightSource", - "ObjectId": -9900, - "ParentId": -9886, + "ObjectId": -1942, + "ParentId": -1190, "Position": { "x": 9.02, "y": 12.1, @@ -105,8 +105,8 @@ }, { "Name": "LightSource", - "ObjectId": -9902, - "ParentId": -9886, + "ObjectId": -1944, + "ParentId": -1190, "Position": { "x": -11.22, "y": 4.47, @@ -122,8 +122,8 @@ }, { "Name": "LightSource", - "ObjectId": -9904, - "ParentId": -9886, + "ObjectId": -1946, + "ParentId": -1190, "Position": { "x": 10.57, "y": 4.47, @@ -139,8 +139,8 @@ }, { "Name": "LightSource", - "ObjectId": -9906, - "ParentId": -9886, + "ObjectId": -1948, + "ParentId": -1190, "Position": { "x": -10.68, "y": 4.47, @@ -156,8 +156,8 @@ }, { "Name": "LightSource", - "ObjectId": -9908, - "ParentId": -9886, + "ObjectId": -1950, + "ParentId": -1190, "Position": { "x": 9.02, "y": 4.47, @@ -173,8 +173,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9910, - "ParentId": -9886, + "ObjectId": -1952, + "ParentId": -1190, "Position": { "x": -18.832, "y": 3.42, @@ -198,8 +198,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9912, - "ParentId": -9886, + "ObjectId": -1954, + "ParentId": -1190, "Position": { "x": -18.832, "y": 3.42, @@ -223,8 +223,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9914, - "ParentId": -9886, + "ObjectId": -1956, + "ParentId": -1190, "Position": { "x": -18.832, "y": 3.42, @@ -248,8 +248,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9916, - "ParentId": -9886, + "ObjectId": -1958, + "ParentId": -1190, "Position": { "x": -18.832, "y": 3.42, @@ -273,8 +273,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9918, - "ParentId": -9886, + "ObjectId": -1960, + "ParentId": -1190, "Position": { "x": -10.86, "y": 3.42, @@ -298,8 +298,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9920, - "ParentId": -9886, + "ObjectId": -1962, + "ParentId": -1190, "Position": { "x": -0.64, "y": 3.42, @@ -323,8 +323,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9922, - "ParentId": -9886, + "ObjectId": -1964, + "ParentId": -1190, "Position": { "x": 11.57, "y": 3.42, @@ -348,8 +348,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9924, - "ParentId": -9886, + "ObjectId": -1966, + "ParentId": -1190, "Position": { "x": 17.26, "y": 3.42, @@ -373,8 +373,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9926, - "ParentId": -9886, + "ObjectId": -1968, + "ParentId": -1190, "Position": { "x": 17.26, "y": 3.42, @@ -398,8 +398,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9928, - "ParentId": -9886, + "ObjectId": -1970, + "ParentId": -1190, "Position": { "x": 18.22, "y": 3.42, @@ -423,8 +423,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9930, - "ParentId": -9886, + "ObjectId": -1972, + "ParentId": -1190, "Position": { "x": 18.22, "y": 3.42, @@ -448,8 +448,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9932, - "ParentId": -9886, + "ObjectId": -1974, + "ParentId": -1190, "Position": { "x": 18.22, "y": 3.42, @@ -473,8 +473,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9934, - "ParentId": -9886, + "ObjectId": -1976, + "ParentId": -1190, "Position": { "x": 18.22, "y": 3.42, @@ -498,8 +498,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9936, - "ParentId": -9886, + "ObjectId": -1978, + "ParentId": -1190, "Position": { "x": 11.48, "y": 3.42, @@ -523,8 +523,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9938, - "ParentId": -9886, + "ObjectId": -1980, + "ParentId": -1190, "Position": { "x": 1.21, "y": 3.42, @@ -548,8 +548,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9940, - "ParentId": -9886, + "ObjectId": -1982, + "ParentId": -1190, "Position": { "x": -9.05, "y": 3.42, @@ -573,8 +573,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9942, - "ParentId": -9886, + "ObjectId": -1984, + "ParentId": -1190, "Position": { "x": -9.05, "y": 3.42, @@ -598,8 +598,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9944, - "ParentId": -9886, + "ObjectId": -1986, + "ParentId": -1190, "Position": { "x": -17.47, "y": 3.42, @@ -623,8 +623,8 @@ }, { "Name": "Spawnpoint", - "ObjectId": -9946, - "ParentId": -9886, + "ObjectId": -1988, + "ParentId": -1190, "Position": { "x": -17.47, "y": 3.42, @@ -648,8 +648,8 @@ }, { "Name": "Teleport", - "ObjectId": -41560, - "ParentId": -9886, + "ObjectId": -1990, + "ParentId": -1190, "Position": { "x": 0.0, "y": 4.224, @@ -673,8 +673,8 @@ }, { "Name": "Teleport", - "ObjectId": -9948, - "ParentId": -9886, + "ObjectId": -1992, + "ParentId": -1190, "Position": { "x": 0.0, "y": 10.93, @@ -698,8 +698,8 @@ }, { "Name": "Wall", - "ObjectId": -9952, - "ParentId": -9886, + "ObjectId": -1994, + "ParentId": -1190, "Position": { "x": 0.053, "y": 2.003, @@ -723,8 +723,8 @@ }, { "Name": "Quad", - "ObjectId": -9954, - "ParentId": -9886, + "ObjectId": -1996, + "ParentId": -1190, "Position": { "x": -0.088, "y": 6.66, @@ -748,8 +748,8 @@ }, { "Name": "Quad", - "ObjectId": -9956, - "ParentId": -9886, + "ObjectId": -1998, + "ParentId": -1190, "Position": { "x": 21.19, "y": 6.683, @@ -773,8 +773,8 @@ }, { "Name": "Quad", - "ObjectId": -9958, - "ParentId": -9886, + "ObjectId": -2000, + "ParentId": -1190, "Position": { "x": -21.56, "y": 6.644, @@ -798,8 +798,8 @@ }, { "Name": "Quad", - "ObjectId": -9960, - "ParentId": -9886, + "ObjectId": -2002, + "ParentId": -1190, "Position": { "x": -0.18, "y": 6.681, @@ -823,8 +823,8 @@ }, { "Name": "Quad", - "ObjectId": -9962, - "ParentId": -9886, + "ObjectId": -2004, + "ParentId": -1190, "Position": { "x": -0.212, "y": 0.41, @@ -848,8 +848,8 @@ }, { "Name": "Quad", - "ObjectId": -9964, - "ParentId": -9886, + "ObjectId": -2006, + "ParentId": -1190, "Position": { "x": -0.101, "y": 13.0, @@ -873,8 +873,8 @@ }, { "Name": "Quad", - "ObjectId": -9966, - "ParentId": -9886, + "ObjectId": -2008, + "ParentId": -1190, "Position": { "x": -0.107, "y": 0.45, @@ -898,8 +898,8 @@ }, { "Name": "Quad", - "ObjectId": -9968, - "ParentId": -9886, + "ObjectId": -2010, + "ParentId": -1190, "Position": { "x": 0.0, "y": 0.45, @@ -923,8 +923,8 @@ }, { "Name": "Quad", - "ObjectId": -9970, - "ParentId": -9886, + "ObjectId": -2012, + "ParentId": -1190, "Position": { "x": -0.119, "y": 0.45, @@ -948,8 +948,8 @@ }, { "Name": "Quad", - "ObjectId": -9972, - "ParentId": -9886, + "ObjectId": -2014, + "ParentId": -1190, "Position": { "x": -0.138, "y": 0.45, @@ -973,8 +973,8 @@ }, { "Name": "Quad", - "ObjectId": -9974, - "ParentId": -9886, + "ObjectId": -2016, + "ParentId": -1190, "Position": { "x": 11.0, "y": 0.45, @@ -998,8 +998,8 @@ }, { "Name": "Quad", - "ObjectId": -9976, - "ParentId": -9886, + "ObjectId": -2018, + "ParentId": -1190, "Position": { "x": -11.0, "y": 0.45, @@ -1023,8 +1023,8 @@ }, { "Name": "Quad", - "ObjectId": -9978, - "ParentId": -9886, + "ObjectId": -2020, + "ParentId": -1190, "Position": { "x": 0.059, "y": 0.43, @@ -1048,8 +1048,8 @@ }, { "Name": "Quad", - "ObjectId": -9980, - "ParentId": -9886, + "ObjectId": -2022, + "ParentId": -1190, "Position": { "x": 16.353, "y": 0.43, @@ -1073,8 +1073,8 @@ }, { "Name": "Quad", - "ObjectId": -9982, - "ParentId": -9886, + "ObjectId": -2024, + "ParentId": -1190, "Position": { "x": -16.57, "y": 0.43, @@ -1098,8 +1098,8 @@ }, { "Name": "Quad", - "ObjectId": -9984, - "ParentId": -9886, + "ObjectId": -2026, + "ParentId": -1190, "Position": { "x": 0.059, "y": 0.43, @@ -1123,8 +1123,8 @@ }, { "Name": "Quad", - "ObjectId": -9986, - "ParentId": -9886, + "ObjectId": -2028, + "ParentId": -1190, "Position": { "x": 0.059, "y": 0.43, @@ -1148,8 +1148,8 @@ }, { "Name": "Quad", - "ObjectId": -9988, - "ParentId": -9886, + "ObjectId": -2030, + "ParentId": -1190, "Position": { "x": 16.353, "y": 0.43, @@ -1173,8 +1173,8 @@ }, { "Name": "Quad", - "ObjectId": -9990, - "ParentId": -9886, + "ObjectId": -2032, + "ParentId": -1190, "Position": { "x": 16.353, "y": 0.43, @@ -1198,8 +1198,8 @@ }, { "Name": "Quad", - "ObjectId": -9992, - "ParentId": -9886, + "ObjectId": -2034, + "ParentId": -1190, "Position": { "x": -16.65, "y": 0.43, @@ -1223,8 +1223,8 @@ }, { "Name": "Quad", - "ObjectId": -9994, - "ParentId": -9886, + "ObjectId": -2036, + "ParentId": -1190, "Position": { "x": -16.49, "y": 0.43, @@ -1248,8 +1248,8 @@ }, { "Name": "Quad", - "ObjectId": -9996, - "ParentId": -9886, + "ObjectId": -2038, + "ParentId": -1190, "Position": { "x": 0.206, "y": 7.97, @@ -1273,8 +1273,8 @@ }, { "Name": "Quad", - "ObjectId": -9998, - "ParentId": -9886, + "ObjectId": -2040, + "ParentId": -1190, "Position": { "x": -0.04, "y": 7.97, @@ -1298,8 +1298,8 @@ }, { "Name": "Quad", - "ObjectId": -10000, - "ParentId": -9886, + "ObjectId": -2042, + "ParentId": -1190, "Position": { "x": -12.9, "y": 7.97, @@ -1323,8 +1323,8 @@ }, { "Name": "Quad", - "ObjectId": -10002, - "ParentId": -9886, + "ObjectId": -2044, + "ParentId": -1190, "Position": { "x": 12.93, "y": 7.97, @@ -1348,8 +1348,8 @@ }, { "Name": "Quad", - "ObjectId": -10004, - "ParentId": -9886, + "ObjectId": -2046, + "ParentId": -1190, "Position": { "x": 0.206, "y": 7.97, @@ -1373,8 +1373,8 @@ }, { "Name": "Quad", - "ObjectId": -10006, - "ParentId": -9886, + "ObjectId": -2048, + "ParentId": -1190, "Position": { "x": 0.206, "y": 7.97, @@ -1398,8 +1398,8 @@ }, { "Name": "Quad", - "ObjectId": -10008, - "ParentId": -9886, + "ObjectId": -2050, + "ParentId": -1190, "Position": { "x": -0.178, "y": 7.97, @@ -1423,8 +1423,8 @@ }, { "Name": "Quad", - "ObjectId": -10010, - "ParentId": -9886, + "ObjectId": -2052, + "ParentId": -1190, "Position": { "x": -0.178, "y": 7.97, @@ -1448,8 +1448,8 @@ }, { "Name": "Quad", - "ObjectId": -10012, - "ParentId": -9886, + "ObjectId": -2054, + "ParentId": -1190, "Position": { "x": -17.761, "y": 7.97, @@ -1473,8 +1473,8 @@ }, { "Name": "Quad", - "ObjectId": -10014, - "ParentId": -9886, + "ObjectId": -2056, + "ParentId": -1190, "Position": { "x": 17.627, "y": 7.97, @@ -1498,8 +1498,8 @@ }, { "Name": "Cube", - "ObjectId": -10016, - "ParentId": -9886, + "ObjectId": -2058, + "ParentId": -1190, "Position": { "x": 0.0042, "y": 4.9301, @@ -1523,8 +1523,8 @@ }, { "Name": "Cube", - "ObjectId": -10018, - "ParentId": -9886, + "ObjectId": -2060, + "ParentId": -1190, "Position": { "x": 4.0, "y": 0.75, @@ -1548,8 +1548,8 @@ }, { "Name": "Cube", - "ObjectId": -10020, - "ParentId": -9886, + "ObjectId": -2062, + "ParentId": -1190, "Position": { "x": -4.0, "y": 0.75, @@ -1573,8 +1573,8 @@ }, { "Name": "Cube", - "ObjectId": -10022, - "ParentId": -9886, + "ObjectId": -2064, + "ParentId": -1190, "Position": { "x": 0.0, "y": 0.75, @@ -1598,8 +1598,8 @@ }, { "Name": "Cube", - "ObjectId": -10024, - "ParentId": -9886, + "ObjectId": -2066, + "ParentId": -1190, "Position": { "x": 0.0, "y": 0.75, @@ -1623,8 +1623,8 @@ }, { "Name": "Cube", - "ObjectId": -10026, - "ParentId": -9886, + "ObjectId": -2068, + "ParentId": -1190, "Position": { "x": -0.017, "y": 7.9, @@ -1648,8 +1648,8 @@ }, { "Name": "Cube", - "ObjectId": -10028, - "ParentId": -9886, + "ObjectId": -2070, + "ParentId": -1190, "Position": { "x": 0.0, "y": 10.481, @@ -1673,8 +1673,8 @@ }, { "Name": "Cube", - "ObjectId": -10030, - "ParentId": -9886, + "ObjectId": -2072, + "ParentId": -1190, "Position": { "x": 0.0, "y": 10.481, @@ -1698,8 +1698,8 @@ }, { "Name": "Cube", - "ObjectId": -10032, - "ParentId": -9886, + "ObjectId": -2074, + "ParentId": -1190, "Position": { "x": 14.0, "y": 10.481, @@ -1723,8 +1723,8 @@ }, { "Name": "Cube", - "ObjectId": -10034, - "ParentId": -9886, + "ObjectId": -2076, + "ParentId": -1190, "Position": { "x": -14.0, "y": 10.481, @@ -1748,8 +1748,8 @@ }, { "Name": "Cube", - "ObjectId": -10036, - "ParentId": -9886, + "ObjectId": -2078, + "ParentId": -1190, "Position": { "x": 20.871, "y": 3.388, @@ -1773,8 +1773,8 @@ }, { "Name": "Cube", - "ObjectId": -10038, - "ParentId": -9886, + "ObjectId": -2080, + "ParentId": -1190, "Position": { "x": -0.005, "y": 0.29, @@ -1798,8 +1798,8 @@ }, { "Name": "Cube", - "ObjectId": -10040, - "ParentId": -9886, + "ObjectId": -2082, + "ParentId": -1190, "Position": { "x": 0.0, "y": 0.0, @@ -1823,8 +1823,8 @@ }, { "Name": "Cube", - "ObjectId": -10042, - "ParentId": -9886, + "ObjectId": -2084, + "ParentId": -1190, "Position": { "x": 0.004, "y": 3.643, @@ -1848,8 +1848,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10044, - "ParentId": -9886, + "ObjectId": -2086, + "ParentId": -1190, "Position": { "x": 0.0, "y": 2.436, @@ -1872,509 +1872,25 @@ } }, { - "Name": "Platform", - "ObjectId": -10046, - "ParentId": -9886, - "Position": { - "x": 0.0, - "y": 8.0789, - "z": 13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10048, - "ParentId": -9886, - "Position": { - "x": -13.0, - "y": 8.0789, - "z": 0.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10050, - "ParentId": -9886, - "Position": { - "x": 13.0, - "y": 8.0789, - "z": 0.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10052, - "ParentId": -9886, - "Position": { - "x": 0.0, - "y": 8.0789, - "z": -13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10054, - "ParentId": -9886, - "Position": { - "x": -13.0, - "y": 8.0789, - "z": -5.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10056, - "ParentId": -9886, - "Position": { - "x": -13.0, - "y": 8.0789, - "z": -10.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10058, - "ParentId": -9886, - "Position": { - "x": -13.0, - "y": 8.0789, - "z": 5.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10060, - "ParentId": -9886, - "Position": { - "x": -13.0, - "y": 8.0789, - "z": 10.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10062, - "ParentId": -9886, - "Position": { - "x": 13.0, - "y": 8.0789, - "z": -5.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10064, - "ParentId": -9886, - "Position": { - "x": 13.0, - "y": 8.0789, - "z": -10.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10066, - "ParentId": -9886, - "Position": { - "x": 13.0, - "y": 8.0789, - "z": 5.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10068, - "ParentId": -9886, - "Position": { - "x": 13.0, - "y": 8.0789, - "z": 10.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10070, - "ParentId": -9886, - "Position": { - "x": 5.0, - "y": 8.0789, - "z": 13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10072, - "ParentId": -9886, - "Position": { - "x": 10.0, - "y": 8.0789, - "z": 13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10074, - "ParentId": -9886, - "Position": { - "x": -10.0, - "y": 8.0789, - "z": 13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10076, - "ParentId": -9886, - "Position": { - "x": -5.0, - "y": 8.0789, - "z": 13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10078, - "ParentId": -9886, - "Position": { - "x": 5.0, - "y": 8.0789, - "z": -13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10080, - "ParentId": -9886, - "Position": { - "x": 10.0, - "y": 8.0789, - "z": -13.0 - }, - "Rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10082, - "ParentId": -9886, - "Position": { - "x": -10.0, - "y": 8.0789, - "z": -13.0 - }, - "Rotation": { + "Name": "Events", + "ObjectId": -2088, + "ParentId": -1190, + "Position": { "x": 0.0, "y": 0.0, "z": 0.0 }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } - }, - { - "Name": "Platform", - "ObjectId": -10084, - "ParentId": -9886, - "Position": { - "x": -5.0, - "y": 8.0789, - "z": -13.0 - }, "Rotation": { "x": 0.0, "y": 0.0, "z": 0.0 }, - "Scale": { - "x": 1.5, - "y": 0.127054334, - "z": 1.5 - }, - "BlockType": 1, - "Properties": { - "PrimitiveType": 2, - "Color": "464646FF" - } + "BlockType": 0 }, { - "Name": "Warhead", - "ObjectId": -10086, - "ParentId": -9886, + "Name": "Atomic Escape", + "ObjectId": -2092, + "ParentId": -2088, "Position": { "x": -5.0, "y": 10.81, @@ -2389,8 +1905,8 @@ }, { "Name": "Cube", - "ObjectId": -10572, - "ParentId": -10086, + "ObjectId": -2788, + "ParentId": -2092, "Position": { "x": 0.2630005, "y": 0.255999565, @@ -2414,8 +1930,8 @@ }, { "Name": "Cube", - "ObjectId": -10574, - "ParentId": -10086, + "ObjectId": -2790, + "ParentId": -2092, "Position": { "x": -0.21149826, "y": 0.1949997, @@ -2439,8 +1955,8 @@ }, { "Name": "Cube", - "ObjectId": -10576, - "ParentId": -10086, + "ObjectId": -2792, + "ParentId": -2092, "Position": { "x": -0.352499, "y": 0.6364994, @@ -2464,8 +1980,8 @@ }, { "Name": "Cube", - "ObjectId": -10578, - "ParentId": -10086, + "ObjectId": -2794, + "ParentId": -2092, "Position": { "x": 0.0225009918, "y": 0.63654995, @@ -2489,8 +2005,8 @@ }, { "Name": "Sphere", - "ObjectId": -10580, - "ParentId": -10086, + "ObjectId": -2796, + "ParentId": -2092, "Position": { "x": 0.0, "y": 0.0, @@ -2514,8 +2030,8 @@ }, { "Name": "Cube", - "ObjectId": -10582, - "ParentId": -10086, + "ObjectId": -2798, + "ParentId": -2092, "Position": { "x": -0.233499527, "y": 0.2414999, @@ -2539,8 +2055,8 @@ }, { "Name": "Cube", - "ObjectId": -10584, - "ParentId": -10086, + "ObjectId": -2800, + "ParentId": -2092, "Position": { "x": 0.397501, "y": 0.6364994, @@ -2564,8 +2080,8 @@ }, { "Name": "Cube", - "ObjectId": -10586, - "ParentId": -10086, + "ObjectId": -2802, + "ParentId": -2092, "Position": { "x": 0.0225009918, "y": 0.63654995, @@ -2589,8 +2105,8 @@ }, { "Name": "Cube", - "ObjectId": -10588, - "ParentId": -10086, + "ObjectId": -2804, + "ParentId": -2092, "Position": { "x": 0.255283356, "y": 0.258999825, @@ -2613,9 +2129,34 @@ } }, { - "Name": "Versus", - "ObjectId": -10088, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2806, + "ParentId": -2092, + "Position": { + "x": 0.0, + "y": -2.7311, + "z": -0.0389995575 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Cock Fights", + "ObjectId": -2094, + "ParentId": -2088, "Position": { "x": -13.635, "y": 9.93, @@ -2629,9 +2170,9 @@ "BlockType": 0 }, { - "Name": "Cube (32)", - "ObjectId": -10652, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2888, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.3072996, @@ -2654,9 +2195,9 @@ } }, { - "Name": "Cube (31)", - "ObjectId": -10654, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2890, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.3782997, @@ -2679,9 +2220,9 @@ } }, { - "Name": "Cube (30)", - "ObjectId": -10656, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2892, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.352199554, @@ -2704,9 +2245,9 @@ } }, { - "Name": "Cube (30)", - "ObjectId": -10658, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2894, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.3777008, @@ -2729,9 +2270,9 @@ } }, { - "Name": "Cube (31)", - "ObjectId": -10660, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2896, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.4038, @@ -2754,9 +2295,9 @@ } }, { - "Name": "Cube (32)", - "ObjectId": -10662, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2898, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.3327999, @@ -2779,9 +2320,9 @@ } }, { - "Name": "Cube (33)", - "ObjectId": -10664, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2900, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.4069004, @@ -2804,9 +2345,9 @@ } }, { - "Name": "Cube (23)", - "ObjectId": -10666, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2902, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.03489971, @@ -2829,9 +2370,9 @@ } }, { - "Name": "Cube (20)", - "ObjectId": -10668, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2904, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.179800034, @@ -2854,9 +2395,9 @@ } }, { - "Name": "Cube (19)", - "ObjectId": -10670, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2906, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.2528, @@ -2879,9 +2420,9 @@ } }, { - "Name": "Cube (16)", - "ObjectId": -10672, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2908, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.372400284, @@ -2904,9 +2445,9 @@ } }, { - "Name": "Cube (22)", - "ObjectId": -10674, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2910, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.0616998672, @@ -2929,9 +2470,9 @@ } }, { - "Name": "Cube (21)", - "ObjectId": -10676, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2912, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.127099991, @@ -2954,9 +2495,9 @@ } }, { - "Name": "Cube (24)", - "ObjectId": -10678, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2914, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.0, @@ -2979,9 +2520,9 @@ } }, { - "Name": "Cube (18)", - "ObjectId": -10680, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2916, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.291399956, @@ -3004,9 +2545,9 @@ } }, { - "Name": "Cube (17)", - "ObjectId": -10682, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2918, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.340900421, @@ -3029,9 +2570,9 @@ } }, { - "Name": "Cube (32)", - "ObjectId": -10684, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2920, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.0346002579, @@ -3054,9 +2595,9 @@ } }, { - "Name": "Cube (16)", - "ObjectId": -10686, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2922, + "ParentId": -2094, "Position": { "x": 0.0, "y": 0.381999969, @@ -3079,9 +2620,9 @@ } }, { - "Name": "Cube (31)", - "ObjectId": -10688, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2924, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.4029007, @@ -3104,9 +2645,9 @@ } }, { - "Name": "Cube (30)", - "ObjectId": -10690, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2926, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.3800001, @@ -3129,9 +2670,9 @@ } }, { - "Name": "Cube (29)", - "ObjectId": -10692, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2928, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.352000237, @@ -3154,9 +2695,9 @@ } }, { - "Name": "Cube (28)", - "ObjectId": -10694, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2930, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.3125, @@ -3179,9 +2720,9 @@ } }, { - "Name": "Cube (27)", - "ObjectId": -10696, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2932, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.246999741, @@ -3204,9 +2745,9 @@ } }, { - "Name": "Cube (24)", - "ObjectId": -10698, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2934, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.07060051, @@ -3229,9 +2770,9 @@ } }, { - "Name": "Cube (26)", - "ObjectId": -10700, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2936, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.186700821, @@ -3254,9 +2795,9 @@ } }, { - "Name": "Cube (25)", - "ObjectId": -10702, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2938, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.124200821, @@ -3279,9 +2820,9 @@ } }, { - "Name": "Cube (1)", - "ObjectId": -10704, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2940, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.02933979, @@ -3304,9 +2845,9 @@ } }, { - "Name": "Cube (5)", - "ObjectId": -10706, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2942, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.353500366, @@ -3329,9 +2870,9 @@ } }, { - "Name": "Cube (6)", - "ObjectId": -10708, - "ParentId": -10088, + "Name": "Cube", + "ObjectId": -2944, + "ParentId": -2094, "Position": { "x": 0.0, "y": -0.0319004059, @@ -3354,9 +2895,34 @@ } }, { - "Name": "Glass", - "ObjectId": -10090, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2946, + "ParentId": -2094, + "Position": { + "x": 0.6350002, + "y": -1.8511, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Dead Jump", + "ObjectId": -2096, + "ParentId": -2088, "Position": { "x": 0.0, "y": 9.603552, @@ -3371,8 +2937,8 @@ }, { "Name": "Cube (1)", - "ObjectId": -10766, - "ParentId": -10090, + "ObjectId": -3044, + "ParentId": -2096, "Position": { "x": 0.0, "y": -0.660552, @@ -3396,8 +2962,8 @@ }, { "Name": "Cube (2)", - "ObjectId": -10768, - "ParentId": -10090, + "ObjectId": -3046, + "ParentId": -2096, "Position": { "x": -0.121125817, "y": 0.488556862, @@ -3421,8 +2987,8 @@ }, { "Name": "Cube (3)", - "ObjectId": -10770, - "ParentId": -10090, + "ObjectId": -3048, + "ParentId": -2096, "Position": { "x": -0.21292901, "y": 0.9476023, @@ -3446,8 +3012,8 @@ }, { "Name": "Cube (4)", - "ObjectId": -10772, - "ParentId": -10090, + "ObjectId": -3050, + "ParentId": -2096, "Position": { "x": -0.202102661, "y": 0.876893044, @@ -3471,8 +3037,8 @@ }, { "Name": "Cube (5)", - "ObjectId": -10774, - "ParentId": -10090, + "ObjectId": -3052, + "ParentId": -2096, "Position": { "x": -0.0522156954, "y": 0.9108591, @@ -3496,8 +3062,8 @@ }, { "Name": "Cube (6)", - "ObjectId": -10776, - "ParentId": -10090, + "ObjectId": -3054, + "ParentId": -2096, "Position": { "x": 0.282376766, "y": 0.8001108, @@ -3521,8 +3087,8 @@ }, { "Name": "Cube (7)", - "ObjectId": -10778, - "ParentId": -10090, + "ObjectId": -3056, + "ParentId": -2096, "Position": { "x": -0.08002722, "y": 1.1269846, @@ -3546,8 +3112,8 @@ }, { "Name": "Cube (9)", - "ObjectId": -10780, - "ParentId": -10090, + "ObjectId": -3058, + "ParentId": -2096, "Position": { "x": -0.337755561, "y": 1.15396214, @@ -3571,8 +3137,8 @@ }, { "Name": "Cube (11)", - "ObjectId": -10782, - "ParentId": -10090, + "ObjectId": -3060, + "ParentId": -2096, "Position": { "x": -0.456405759, "y": 1.03210545, @@ -3596,8 +3162,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -10784, - "ParentId": -10090, + "ObjectId": -3062, + "ParentId": -2096, "Position": { "x": -0.961677432, "y": 1.16412449, @@ -3620,9 +3186,34 @@ } }, { - "Name": "Zombie", - "ObjectId": -10092, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -3064, + "ParentId": -2096, + "Position": { + "x": 0.0, + "y": -1.52465153, + "z": -0.6680012 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Zombie Infection", + "ObjectId": -2098, + "ParentId": -2088, "Position": { "x": 13.5960007, "y": 8.0789, @@ -3637,8 +3228,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10216, - "ParentId": -10092, + "ObjectId": -2382, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 1.96399975, @@ -3662,8 +3253,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10218, - "ParentId": -10092, + "ObjectId": -2384, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 1.569499, @@ -3687,8 +3278,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10220, - "ParentId": -10092, + "ObjectId": -2386, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 2.3581, @@ -3712,8 +3303,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -10222, - "ParentId": -10092, + "ObjectId": -2388, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 1.96419907, @@ -3737,8 +3328,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10224, - "ParentId": -10092, + "ObjectId": -2390, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 2.06919956, @@ -3762,8 +3353,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10226, - "ParentId": -10092, + "ObjectId": -2392, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 1.96419907, @@ -3787,8 +3378,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10228, - "ParentId": -10092, + "ObjectId": -2394, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 2.06919956, @@ -3812,8 +3403,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10230, - "ParentId": -10092, + "ObjectId": -2396, + "ParentId": -2098, "Position": { "x": 0.107000351, "y": 1.74469948, @@ -3836,9 +3427,34 @@ } }, { - "Name": "GunGame", - "ObjectId": -10094, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2398, + "ParentId": -2098, + "Position": { + "x": -0.5960007, + "y": 0.0, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Gun Game", + "ObjectId": -2100, + "ParentId": -2088, "Position": { "x": 0.05000019, "y": 10.28, @@ -3853,8 +3469,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10414, - "ParentId": -10094, + "ObjectId": -2620, + "ParentId": -2100, "Position": { "x": -1.0839, "y": 0.2976, @@ -3878,8 +3494,8 @@ }, { "Name": "Cube (4)", - "ObjectId": -10416, - "ParentId": -10094, + "ObjectId": -2622, + "ParentId": -2100, "Position": { "x": -0.8313, "y": 0.0621, @@ -3903,8 +3519,8 @@ }, { "Name": "Cube (8)", - "ObjectId": -10418, - "ParentId": -10094, + "ObjectId": -2624, + "ParentId": -2100, "Position": { "x": 0.0875613242, "y": -0.184064865, @@ -3928,8 +3544,8 @@ }, { "Name": "Cube (9)", - "ObjectId": -10420, - "ParentId": -10094, + "ObjectId": -2626, + "ParentId": -2100, "Position": { "x": 0.234274223, "y": -0.281615257, @@ -3953,8 +3569,8 @@ }, { "Name": "Cube (10)", - "ObjectId": -10422, - "ParentId": -10094, + "ObjectId": -2628, + "ParentId": -2100, "Position": { "x": 0.421461463, "y": -0.2811041, @@ -3978,8 +3594,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10424, - "ParentId": -10094, + "ObjectId": -2630, + "ParentId": -2100, "Position": { "x": 0.556365252, "y": -0.426458359, @@ -4003,8 +3619,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10426, - "ParentId": -10094, + "ObjectId": -2632, + "ParentId": -2100, "Position": { "x": 0.6936631, "y": -0.544868469, @@ -4028,8 +3644,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -10428, - "ParentId": -10094, + "ObjectId": -2634, + "ParentId": -2100, "Position": { "x": 0.09549345, "y": -0.356781, @@ -4053,8 +3669,8 @@ }, { "Name": "Cylinder (4)", - "ObjectId": -10430, - "ParentId": -10094, + "ObjectId": -2636, + "ParentId": -2100, "Position": { "x": -0.158929214, "y": -0.190396309, @@ -4078,8 +3694,8 @@ }, { "Name": "Cylinder (12)", - "ObjectId": -10432, - "ParentId": -10094, + "ObjectId": -2638, + "ParentId": -2100, "Position": { "x": -0.008875836, "y": -0.254058838, @@ -4103,8 +3719,8 @@ }, { "Name": "Cylinder (1)", - "ObjectId": -10434, - "ParentId": -10094, + "ObjectId": -2640, + "ParentId": -2100, "Position": { "x": -1.0839, "y": 0.2976, @@ -4128,8 +3744,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10436, - "ParentId": -10094, + "ObjectId": -2642, + "ParentId": -2100, "Position": { "x": 0.8645, "y": -0.7869, @@ -4153,8 +3769,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -10438, - "ParentId": -10094, + "ObjectId": -2644, + "ParentId": -2100, "Position": { "x": 0.189826325, "y": -0.4293928, @@ -4178,8 +3794,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -10440, - "ParentId": -10094, + "ObjectId": -2646, + "ParentId": -2100, "Position": { "x": 0.0119304173, "y": -0.45081234, @@ -4201,10 +3817,35 @@ "Color": "525252FF" } }, + { + "Name": "Platform", + "ObjectId": -2648, + "ParentId": -2100, + "Position": { + "x": -0.05000019, + "y": -2.2010994, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, { "Name": "Puzzle", - "ObjectId": -10096, - "ParentId": -9886, + "ObjectId": -2102, + "ParentId": -2088, "Position": { "x": -13.73, "y": 9.506, @@ -4219,8 +3860,8 @@ }, { "Name": "Quad", - "ObjectId": -10344, - "ParentId": -10096, + "ObjectId": -2536, + "ParentId": -2102, "Position": { "x": 0.0, "y": 0.0, @@ -4244,8 +3885,8 @@ }, { "Name": "Quad", - "ObjectId": -10346, - "ParentId": -10096, + "ObjectId": -2538, + "ParentId": -2102, "Position": { "x": 0.0, "y": 0.0, @@ -4269,8 +3910,8 @@ }, { "Name": "Quad", - "ObjectId": -10348, - "ParentId": -10096, + "ObjectId": -2540, + "ParentId": -2102, "Position": { "x": 0.0, "y": 0.0, @@ -4294,8 +3935,8 @@ }, { "Name": "Quad", - "ObjectId": -10350, - "ParentId": -10096, + "ObjectId": -2542, + "ParentId": -2102, "Position": { "x": 0.0, "y": 0.6816006, @@ -4319,8 +3960,8 @@ }, { "Name": "Quad", - "ObjectId": -10352, - "ParentId": -10096, + "ObjectId": -2544, + "ParentId": -2102, "Position": { "x": 0.0, "y": 0.6816006, @@ -4344,8 +3985,8 @@ }, { "Name": "Quad", - "ObjectId": -10354, - "ParentId": -10096, + "ObjectId": -2546, + "ParentId": -2102, "Position": { "x": 0.0, "y": 0.6816006, @@ -4369,8 +4010,8 @@ }, { "Name": "Quad", - "ObjectId": -10356, - "ParentId": -10096, + "ObjectId": -2548, + "ParentId": -2102, "Position": { "x": -0.0167999268, "y": 0.6612005, @@ -4394,8 +4035,8 @@ }, { "Name": "Quad", - "ObjectId": -10358, - "ParentId": -10096, + "ObjectId": -2550, + "ParentId": -2102, "Position": { "x": 0.0, "y": 1.35480118, @@ -4419,8 +4060,8 @@ }, { "Name": "Quad", - "ObjectId": -10360, - "ParentId": -10096, + "ObjectId": -2552, + "ParentId": -2102, "Position": { "x": 0.0, "y": 1.35480118, @@ -4444,8 +4085,8 @@ }, { "Name": "Quad", - "ObjectId": -10362, - "ParentId": -10096, + "ObjectId": -2554, + "ParentId": -2102, "Position": { "x": 0.0, "y": 1.35480118, @@ -4468,9 +4109,34 @@ } }, { - "Name": "Boss", - "ObjectId": -10098, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2556, + "ParentId": -2102, + "Position": { + "x": 0.729999542, + "y": -1.42709923, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Boss Battle", + "ObjectId": -2104, + "ParentId": -2088, "Position": { "x": -13.0, "y": 10.063489, @@ -4485,8 +4151,8 @@ }, { "Name": "Cylinder (2)", - "ObjectId": -10236, - "ParentId": -10098, + "ObjectId": -2404, + "ParentId": -2104, "Position": { "x": -0.0340003967, "y": -0.353184968, @@ -4510,8 +4176,8 @@ }, { "Name": "Sphere (1)", - "ObjectId": -10238, - "ParentId": -10098, + "ObjectId": -2406, + "ParentId": -2104, "Position": { "x": -0.0340003967, "y": -0.118185289, @@ -4535,8 +4201,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10240, - "ParentId": -10098, + "ObjectId": -2408, + "ParentId": -2104, "Position": { "x": -0.0340003967, "y": 0.181814969, @@ -4560,8 +4226,8 @@ }, { "Name": "Sphere", - "ObjectId": -10242, - "ParentId": -10098, + "ObjectId": -2410, + "ParentId": -2104, "Position": { "x": -0.0340003967, "y": 0.481815219, @@ -4585,8 +4251,8 @@ }, { "Name": "Cylinder (1)", - "ObjectId": -10244, - "ParentId": -10098, + "ObjectId": -2412, + "ParentId": -2104, "Position": { "x": -0.0340003967, "y": -0.353184968, @@ -4610,8 +4276,8 @@ }, { "Name": "Capsule (1)", - "ObjectId": -10246, - "ParentId": -10098, + "ObjectId": -2414, + "ParentId": -2104, "Position": { "x": 0.350999832, "y": 0.4658154, @@ -4634,9 +4300,34 @@ } }, { - "Name": "Lava", - "ObjectId": -10100, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2416, + "ParentId": -2104, + "Position": { + "x": 0.0, + "y": -1.98458862, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "The floor is LAVA", + "ObjectId": -2106, + "ParentId": -2088, "Position": { "x": -13.73, "y": 9.506, @@ -4651,8 +4342,8 @@ }, { "Name": "Quad", - "ObjectId": -10612, - "ParentId": -10100, + "ObjectId": -2842, + "ParentId": -2106, "Position": { "x": 0.0, "y": 0.0, @@ -4676,8 +4367,8 @@ }, { "Name": "Quad", - "ObjectId": -10614, - "ParentId": -10100, + "ObjectId": -2844, + "ParentId": -2106, "Position": { "x": -0.02159977, "y": 0.129599571, @@ -4701,8 +4392,8 @@ }, { "Name": "Quad", - "ObjectId": -10616, - "ParentId": -10100, + "ObjectId": -2846, + "ParentId": -2106, "Position": { "x": -0.00899982452, "y": 0.6816006, @@ -4726,8 +4417,8 @@ }, { "Name": "Quad", - "ObjectId": -10618, - "ParentId": -10100, + "ObjectId": -2848, + "ParentId": -2106, "Position": { "x": -0.0167999268, "y": 0.6612005, @@ -4751,8 +4442,8 @@ }, { "Name": "Quad", - "ObjectId": -10620, - "ParentId": -10100, + "ObjectId": -2850, + "ParentId": -2106, "Position": { "x": -0.029999733, "y": 1.28040028, @@ -4776,8 +4467,8 @@ }, { "Name": "Quad", - "ObjectId": -10622, - "ParentId": -10100, + "ObjectId": -2852, + "ParentId": -2106, "Position": { "x": 0.0, "y": 1.35480118, @@ -4800,9 +4491,34 @@ } }, { - "Name": "Deathmatch", - "ObjectId": -10102, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2854, + "ParentId": -2106, + "Position": { + "x": 0.729999542, + "y": -1.42709923, + "z": 0.031999588 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Team Death-Match", + "ObjectId": -2108, + "ParentId": -2088, "Position": { "x": -13.0, "y": 8.0789, @@ -4817,8 +4533,8 @@ }, { "Name": "Cylinder (2)", - "ObjectId": -10536, - "ParentId": -10102, + "ObjectId": -2748, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.89871979, @@ -4842,8 +4558,8 @@ }, { "Name": "Cylinder (3)", - "ObjectId": -10538, - "ParentId": -10102, + "ObjectId": -2750, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.36906528, @@ -4867,8 +4583,8 @@ }, { "Name": "Cylinder (4)", - "ObjectId": -10540, - "ParentId": -10102, + "ObjectId": -2752, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 1.954463, @@ -4892,8 +4608,8 @@ }, { "Name": "Cube (1)", - "ObjectId": -10542, - "ParentId": -10102, + "ObjectId": -2754, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 1.87783432, @@ -4917,8 +4633,8 @@ }, { "Name": "Cube (2)", - "ObjectId": -10544, - "ParentId": -10102, + "ObjectId": -2756, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 1.59912872, @@ -4942,8 +4658,8 @@ }, { "Name": "Cube (3)", - "ObjectId": -10546, - "ParentId": -10102, + "ObjectId": -2758, + "ParentId": -2108, "Position": { "x": -0.5185003, "y": 1.73848152, @@ -4967,8 +4683,8 @@ }, { "Name": "Cube (6)", - "ObjectId": -10548, - "ParentId": -10102, + "ObjectId": -2760, + "ParentId": -2108, "Position": { "x": -0.5567503, "y": 1.63431168, @@ -4992,8 +4708,8 @@ }, { "Name": "Cube (7)", - "ObjectId": -10550, - "ParentId": -10102, + "ObjectId": -2762, + "ParentId": -2108, "Position": { "x": -0.5567503, "y": 1.84265137, @@ -5017,8 +4733,8 @@ }, { "Name": "Cylinder (6)", - "ObjectId": -10552, - "ParentId": -10102, + "ObjectId": -2764, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 1.8850193, @@ -5042,8 +4758,8 @@ }, { "Name": "Cylinder (7)", - "ObjectId": -10554, - "ParentId": -10102, + "ObjectId": -2766, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.01596165, @@ -5067,8 +4783,8 @@ }, { "Name": "Cube (9)", - "ObjectId": -10556, - "ParentId": -10102, + "ObjectId": -2768, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.31787586, @@ -5092,8 +4808,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10558, - "ParentId": -10102, + "ObjectId": -2770, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.29153347, @@ -5117,8 +4833,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10560, - "ParentId": -10102, + "ObjectId": -2772, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.241763, @@ -5142,8 +4858,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10562, - "ParentId": -10102, + "ObjectId": -2774, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 2.327444, @@ -5167,8 +4883,8 @@ }, { "Name": "Cylinder (5)", - "ObjectId": -10564, - "ParentId": -10102, + "ObjectId": -2776, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 3.21533585, @@ -5192,8 +4908,8 @@ }, { "Name": "Sphere", - "ObjectId": -10566, - "ParentId": -10102, + "ObjectId": -2778, + "ParentId": -2108, "Position": { "x": -0.6700001, "y": 1.95328617, @@ -5215,10 +4931,35 @@ "Color": "352500FF" } }, + { + "Name": "Platform", + "ObjectId": -2780, + "ParentId": -2108, + "Position": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, { "Name": "Battle", - "ObjectId": -10104, - "ParentId": -9886, + "ObjectId": -2110, + "ParentId": -2088, "Position": { "x": 13.59, "y": 11.075, @@ -5233,8 +4974,8 @@ }, { "Name": "Cube", - "ObjectId": -10800, - "ParentId": -10104, + "ObjectId": -3096, + "ParentId": -2110, "Position": { "x": 0.0, "y": 0.0, @@ -5258,8 +4999,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10802, - "ParentId": -10104, + "ObjectId": -3098, + "ParentId": -2110, "Position": { "x": 0.0, "y": -0.7779999, @@ -5283,8 +5024,8 @@ }, { "Name": "Cylinder (1)", - "ObjectId": -10804, - "ParentId": -10104, + "ObjectId": -3100, + "ParentId": -2110, "Position": { "x": 0.0, "y": 0.10606575, @@ -5308,8 +5049,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10806, - "ParentId": -10104, + "ObjectId": -3102, + "ParentId": -2110, "Position": { "x": 0.0, "y": -0.10606575, @@ -5333,8 +5074,8 @@ }, { "Name": "Cube (4)", - "ObjectId": -10808, - "ParentId": -10104, + "ObjectId": -3104, + "ParentId": -2110, "Position": { "x": 0.0, "y": 0.0, @@ -5358,8 +5099,8 @@ }, { "Name": "Cube (3)", - "ObjectId": -10810, - "ParentId": -10104, + "ObjectId": -3106, + "ParentId": -2110, "Position": { "x": 0.0, "y": 0.0, @@ -5383,8 +5124,8 @@ }, { "Name": "Cube (2)", - "ObjectId": -10812, - "ParentId": -10104, + "ObjectId": -3108, + "ParentId": -2110, "Position": { "x": 0.0, "y": 0.0, @@ -5408,8 +5149,8 @@ }, { "Name": "Cube (1)", - "ObjectId": -10814, - "ParentId": -10104, + "ObjectId": -3110, + "ParentId": -2110, "Position": { "x": 0.0, "y": 0.0, @@ -5432,9 +5173,34 @@ } }, { - "Name": "Football", - "ObjectId": -10106, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -3112, + "ParentId": -2110, + "Position": { + "x": -0.590000153, + "y": -2.99609947, + "z": 0.8649993 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Soccer", + "ObjectId": -2112, + "ParentId": -2088, "Position": { "x": 12.9900017, "y": 10.769, @@ -5449,8 +5215,8 @@ }, { "Name": "Sphere", - "ObjectId": -10720, - "ParentId": -10106, + "ObjectId": -2964, + "ParentId": -2112, "Position": { "x": 0.0, "y": 0.0, @@ -5473,9 +5239,34 @@ } }, { - "Name": "Line", - "ObjectId": -10108, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2966, + "ParentId": -2112, + "Position": { + "x": 0.00999832153, + "y": -2.69009972, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "DeathLine", + "ObjectId": -2114, + "ParentId": -2088, "Position": { "x": 13.0, "y": 9.553, @@ -5490,8 +5281,8 @@ }, { "Name": "Quad", - "ObjectId": -10758, - "ParentId": -10108, + "ObjectId": -3034, + "ParentId": -2114, "Position": { "x": 0.0, "y": 1.025, @@ -5515,8 +5306,8 @@ }, { "Name": "Quad (1)", - "ObjectId": -10760, - "ParentId": -10108, + "ObjectId": -3036, + "ParentId": -2114, "Position": { "x": 0.0, "y": -0.1696, @@ -5540,8 +5331,8 @@ }, { "Name": "Quad (2)", - "ObjectId": -10762, - "ParentId": -10108, + "ObjectId": -3038, + "ParentId": -2114, "Position": { "x": 0.0, "y": 0.9674, @@ -5564,9 +5355,34 @@ } }, { - "Name": "Knife", - "ObjectId": -10110, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -3040, + "ParentId": -2114, + "Position": { + "x": 0.0, + "y": -1.47410011, + "z": -0.236999512 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Knives of Death", + "ObjectId": -2116, + "ParentId": -2088, "Position": { "x": 13.5475006, "y": 9.628963, @@ -5581,8 +5397,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10336, - "ParentId": -10110, + "ObjectId": -2526, + "ParentId": -2116, "Position": { "x": 0.0, "y": 0.319119453, @@ -5606,8 +5422,8 @@ }, { "Name": "Sphere", - "ObjectId": -10338, - "ParentId": -10110, + "ObjectId": -2528, + "ParentId": -2116, "Position": { "x": 0.0, "y": 1.29524136, @@ -5631,8 +5447,8 @@ }, { "Name": "Cube", - "ObjectId": -10340, - "ParentId": -10110, + "ObjectId": -2530, + "ParentId": -2116, "Position": { "x": -0.0334997177, "y": 0.4634304, @@ -5655,9 +5471,34 @@ } }, { - "Name": "Jail", - "ObjectId": -10112, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2532, + "ParentId": -2116, + "Position": { + "x": -0.5475006, + "y": -1.55006313, + "z": -0.20249939 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Simon's Prison", + "ObjectId": -2118, + "ParentId": -2088, "Position": { "x": 5.0, "y": 10.4980145, @@ -5672,8 +5513,8 @@ }, { "Name": "Cube", - "ObjectId": -10374, - "ParentId": -10112, + "ObjectId": -2576, + "ParentId": -2118, "Position": { "x": 0.024, "y": -0.0629, @@ -5697,8 +5538,8 @@ }, { "Name": "Cube", - "ObjectId": -10376, - "ParentId": -10112, + "ObjectId": -2578, + "ParentId": -2118, "Position": { "x": -1.06, "y": -1.3362, @@ -5722,8 +5563,8 @@ }, { "Name": "Cube", - "ObjectId": -10378, - "ParentId": -10112, + "ObjectId": -2580, + "ParentId": -2118, "Position": { "x": -1.06, "y": -1.3362, @@ -5747,8 +5588,8 @@ }, { "Name": "Cube", - "ObjectId": -10380, - "ParentId": -10112, + "ObjectId": -2582, + "ParentId": -2118, "Position": { "x": -1.06, "y": -1.3362, @@ -5772,8 +5613,8 @@ }, { "Name": "Cube", - "ObjectId": -10382, - "ParentId": -10112, + "ObjectId": -2584, + "ParentId": -2118, "Position": { "x": -1.06, "y": -1.3362, @@ -5797,8 +5638,8 @@ }, { "Name": "Cube", - "ObjectId": -10384, - "ParentId": -10112, + "ObjectId": -2586, + "ParentId": -2118, "Position": { "x": -1.06, "y": -1.3362, @@ -5822,8 +5663,8 @@ }, { "Name": "Cube", - "ObjectId": -10386, - "ParentId": -10112, + "ObjectId": -2588, + "ParentId": -2118, "Position": { "x": 1.06699991, "y": -1.3362, @@ -5847,8 +5688,8 @@ }, { "Name": "Cube", - "ObjectId": -10388, - "ParentId": -10112, + "ObjectId": -2590, + "ParentId": -2118, "Position": { "x": 1.06699991, "y": -1.3362, @@ -5872,8 +5713,8 @@ }, { "Name": "Cube", - "ObjectId": -10390, - "ParentId": -10112, + "ObjectId": -2592, + "ParentId": -2118, "Position": { "x": 1.06699991, "y": -1.3362, @@ -5897,8 +5738,8 @@ }, { "Name": "Cube", - "ObjectId": -10392, - "ParentId": -10112, + "ObjectId": -2594, + "ParentId": -2118, "Position": { "x": 1.06699991, "y": -1.3362, @@ -5922,8 +5763,8 @@ }, { "Name": "Cube", - "ObjectId": -10394, - "ParentId": -10112, + "ObjectId": -2596, + "ParentId": -2118, "Position": { "x": 1.067, "y": -1.3362, @@ -5947,8 +5788,8 @@ }, { "Name": "Cube", - "ObjectId": -10396, - "ParentId": -10112, + "ObjectId": -2598, + "ParentId": -2118, "Position": { "x": -1.06, "y": -1.3362, @@ -5972,8 +5813,8 @@ }, { "Name": "Cube", - "ObjectId": -10398, - "ParentId": -10112, + "ObjectId": -2600, + "ParentId": -2118, "Position": { "x": 1.107, "y": -1.3362, @@ -5996,9 +5837,34 @@ } }, { - "Name": "Zombie2", - "ObjectId": -10114, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2602, + "ParentId": -2118, + "Position": { + "x": 0.0, + "y": -2.419114, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Zombie Survival", + "ObjectId": -2120, + "ParentId": -2088, "Position": { "x": 10.0300007, "y": 8.0789, @@ -6013,8 +5879,8 @@ }, { "Name": "Cube (17)", - "ObjectId": -10448, - "ParentId": -10114, + "ObjectId": -2658, + "ParentId": -2120, "Position": { "x": -1.32499981, "y": 0.563099861, @@ -6038,8 +5904,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10450, - "ParentId": -10114, + "ObjectId": -2660, + "ParentId": -2120, "Position": { "x": 1.25500011, "y": 0.563099861, @@ -6063,8 +5929,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10452, - "ParentId": -10114, + "ObjectId": -2662, + "ParentId": -2120, "Position": { "x": -1.28899956, "y": 1.22610009, @@ -6088,8 +5954,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10454, - "ParentId": -10114, + "ObjectId": -2664, + "ParentId": -2120, "Position": { "x": -1.15499973, "y": 1.06309986, @@ -6113,8 +5979,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10456, - "ParentId": -10114, + "ObjectId": -2666, + "ParentId": -2120, "Position": { "x": -0.875, "y": 1.06309986, @@ -6138,8 +6004,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -10458, - "ParentId": -10114, + "ObjectId": -2668, + "ParentId": -2120, "Position": { "x": -0.595000267, "y": 1.06309986, @@ -6163,8 +6029,8 @@ }, { "Name": "Cube (10)", - "ObjectId": -10460, - "ParentId": -10114, + "ObjectId": -2670, + "ParentId": -2120, "Position": { "x": -0.31499958, "y": 1.06309986, @@ -6188,8 +6054,8 @@ }, { "Name": "Cube (11)", - "ObjectId": -10462, - "ParentId": -10114, + "ObjectId": -2672, + "ParentId": -2120, "Position": { "x": 1.22190011, "y": 0.904899657, @@ -6213,8 +6079,8 @@ }, { "Name": "Cube (8)", - "ObjectId": -10464, - "ParentId": -10114, + "ObjectId": -2674, + "ParentId": -2120, "Position": { "x": 1.08500016, "y": 1.06309986, @@ -6238,8 +6104,8 @@ }, { "Name": "Cube (7)", - "ObjectId": -10466, - "ParentId": -10114, + "ObjectId": -2676, + "ParentId": -2120, "Position": { "x": 0.8050004, "y": 1.06309986, @@ -6263,8 +6129,8 @@ }, { "Name": "Cube (6)", - "ObjectId": -10468, - "ParentId": -10114, + "ObjectId": -2678, + "ParentId": -2120, "Position": { "x": 0.5250006, "y": 1.06309986, @@ -6288,8 +6154,8 @@ }, { "Name": "Cube (5)", - "ObjectId": -10470, - "ParentId": -10114, + "ObjectId": -2680, + "ParentId": -2120, "Position": { "x": 0.2449999, "y": 1.06309986, @@ -6313,8 +6179,8 @@ }, { "Name": "Cube (3)", - "ObjectId": -10472, - "ParentId": -10114, + "ObjectId": -2682, + "ParentId": -2120, "Position": { "x": -0.0349998474, "y": 1.2731, @@ -6338,8 +6204,8 @@ }, { "Name": "Cube (2)", - "ObjectId": -10474, - "ParentId": -10114, + "ObjectId": -2684, + "ParentId": -2120, "Position": { "x": -0.0349998474, "y": 0.8530998, @@ -6363,8 +6229,8 @@ }, { "Name": "Cube (1)", - "ObjectId": -10476, - "ParentId": -10114, + "ObjectId": -2686, + "ParentId": -2120, "Position": { "x": -0.0349998474, "y": 1.06309986, @@ -6388,8 +6254,8 @@ }, { "Name": "Cube", - "ObjectId": -10478, - "ParentId": -10114, + "ObjectId": -2688, + "ParentId": -2120, "Position": { "x": -0.0349998474, "y": 1.06309986, @@ -6413,8 +6279,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10480, - "ParentId": -10114, + "ObjectId": -2690, + "ParentId": -2120, "Position": { "x": -0.859999657, "y": 1.96399975, @@ -6438,8 +6304,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10482, - "ParentId": -10114, + "ObjectId": -2692, + "ParentId": -2120, "Position": { "x": -0.859999657, "y": 1.569499, @@ -6463,8 +6329,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10484, - "ParentId": -10114, + "ObjectId": -2694, + "ParentId": -2120, "Position": { "x": -0.859999657, "y": 2.3581, @@ -6488,8 +6354,8 @@ }, { "Name": "Cube (25)", - "ObjectId": -10486, - "ParentId": -10114, + "ObjectId": -2696, + "ParentId": -2120, "Position": { "x": 0.6918001, "y": 1.86810017, @@ -6513,8 +6379,8 @@ }, { "Name": "Cube (26)", - "ObjectId": -10488, - "ParentId": -10114, + "ObjectId": -2698, + "ParentId": -2120, "Position": { "x": 0.6733999, "y": 1.80560017, @@ -6538,8 +6404,8 @@ }, { "Name": "Cube (24)", - "ObjectId": -10490, - "ParentId": -10114, + "ObjectId": -2700, + "ParentId": -2120, "Position": { "x": 0.72369957, "y": 1.92169952, @@ -6563,8 +6429,8 @@ }, { "Name": "Cube (27)", - "ObjectId": -10492, - "ParentId": -10114, + "ObjectId": -2702, + "ParentId": -2120, "Position": { "x": 0.67179966, "y": 1.74529934, @@ -6588,8 +6454,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10494, - "ParentId": -10114, + "ObjectId": -2704, + "ParentId": -2120, "Position": { "x": 0.869000435, "y": 2.3743, @@ -6613,8 +6479,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -10496, - "ParentId": -10114, + "ObjectId": -2706, + "ParentId": -2120, "Position": { "x": 0.7637005, "y": 1.95769978, @@ -6638,8 +6504,8 @@ }, { "Name": "Cube (17)", - "ObjectId": -10498, - "ParentId": -10114, + "ObjectId": -2708, + "ParentId": -2120, "Position": { "x": 1.03009987, "y": 2.3331995, @@ -6663,8 +6529,8 @@ }, { "Name": "Cube (18)", - "ObjectId": -10500, - "ParentId": -10114, + "ObjectId": -2710, + "ParentId": -2120, "Position": { "x": 1.07079983, "y": 2.2837, @@ -6688,8 +6554,8 @@ }, { "Name": "Cube (24)", - "ObjectId": -10502, - "ParentId": -10114, + "ObjectId": -2712, + "ParentId": -2120, "Position": { "x": 0.8901005, "y": 1.9923, @@ -6713,8 +6579,8 @@ }, { "Name": "Cube (21)", - "ObjectId": -10504, - "ParentId": -10114, + "ObjectId": -2714, + "ParentId": -2120, "Position": { "x": 1.07649994, "y": 2.1194, @@ -6738,8 +6604,8 @@ }, { "Name": "Cube (22)", - "ObjectId": -10506, - "ParentId": -10114, + "ObjectId": -2716, + "ParentId": -2120, "Position": { "x": 1.04399967, "y": 2.054, @@ -6763,8 +6629,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10508, - "ParentId": -10114, + "ObjectId": -2718, + "ParentId": -2120, "Position": { "x": 0.98429966, "y": 2.36469936, @@ -6788,8 +6654,8 @@ }, { "Name": "Cube (19)", - "ObjectId": -10510, - "ParentId": -10114, + "ObjectId": -2720, + "ParentId": -2120, "Position": { "x": 1.08469963, "y": 2.2451, @@ -6813,8 +6679,8 @@ }, { "Name": "Cube (20)", - "ObjectId": -10512, - "ParentId": -10114, + "ObjectId": -2722, + "ParentId": -2120, "Position": { "x": 1.08769989, "y": 2.1721, @@ -6838,8 +6704,8 @@ }, { "Name": "Cube (23)", - "ObjectId": -10514, - "ParentId": -10114, + "ObjectId": -2724, + "ParentId": -2120, "Position": { "x": 1.0176, "y": 2.02719975, @@ -6863,8 +6729,8 @@ }, { "Name": "Cube (33)", - "ObjectId": -10516, - "ParentId": -10114, + "ObjectId": -2726, + "ParentId": -2120, "Position": { "x": 0.8529997, "y": 1.60999966, @@ -6888,8 +6754,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -10518, - "ParentId": -10114, + "ObjectId": -2728, + "ParentId": -2120, "Position": { "x": 0.7276001, "y": 2.34449959, @@ -6913,8 +6779,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -10520, - "ParentId": -10114, + "ObjectId": -2730, + "ParentId": -2120, "Position": { "x": 0.7652998, "y": 2.37059975, @@ -6938,8 +6804,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -10522, - "ParentId": -10114, + "ObjectId": -2732, + "ParentId": -2120, "Position": { "x": 0.6949997, "y": 2.2865, @@ -6963,8 +6829,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -10524, - "ParentId": -10114, + "ObjectId": -2734, + "ParentId": -2120, "Position": { "x": -0.266999245, "y": 1.96419907, @@ -6988,8 +6854,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10526, - "ParentId": -10114, + "ObjectId": -2736, + "ParentId": -2120, "Position": { "x": -0.112999916, "y": 2.06919956, @@ -7013,8 +6879,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10528, - "ParentId": -10114, + "ObjectId": -2738, + "ParentId": -2120, "Position": { "x": 0.345000267, "y": 1.96419907, @@ -7038,8 +6904,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -10530, - "ParentId": -10114, + "ObjectId": -2740, + "ParentId": -2120, "Position": { "x": 0.190999985, "y": 2.06919956, @@ -7063,8 +6929,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10532, - "ParentId": -10114, + "ObjectId": -2742, + "ParentId": -2120, "Position": { "x": 0.03900051, "y": 1.74469948, @@ -7087,9 +6953,34 @@ } }, { - "Name": "HnS", - "ObjectId": -10116, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2744, + "ParentId": -2120, + "Position": { + "x": -0.0300006866, + "y": 0.0, + "z": -0.529001236 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Tag", + "ObjectId": -2122, + "ParentId": -2088, "Position": { "x": -9.927, "y": 10.28, @@ -7104,8 +6995,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -10260, - "ParentId": -10116, + "ObjectId": -2438, + "ParentId": -2122, "Position": { "x": -1.066, "y": -0.0122995377, @@ -7129,8 +7020,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10262, - "ParentId": -10116, + "ObjectId": -2440, + "ParentId": -2122, "Position": { "x": -0.6000004, "y": -0.0122995377, @@ -7154,8 +7045,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10264, - "ParentId": -10116, + "ObjectId": -2442, + "ParentId": -2122, "Position": { "x": -0.8330002, "y": 0.004699707, @@ -7179,8 +7070,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -10266, - "ParentId": -10116, + "ObjectId": -2444, + "ParentId": -2122, "Position": { "x": -0.2329998, "y": -0.0129003525, @@ -7204,8 +7095,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -10268, - "ParentId": -10116, + "ObjectId": -2446, + "ParentId": -2122, "Position": { "x": 0.0, "y": -0.0129003525, @@ -7229,8 +7120,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -10270, - "ParentId": -10116, + "ObjectId": -2448, + "ParentId": -2122, "Position": { "x": 0.2329998, "y": -0.0129003525, @@ -7254,8 +7145,8 @@ }, { "Name": "Cube (25)", - "ObjectId": -10272, - "ParentId": -10116, + "ObjectId": -2450, + "ParentId": -2122, "Position": { "x": 0.9913006, "y": -0.124199867, @@ -7279,8 +7170,8 @@ }, { "Name": "Cube (26)", - "ObjectId": -10274, - "ParentId": -10116, + "ObjectId": -2452, + "ParentId": -2122, "Position": { "x": 1.00970078, "y": -0.186699867, @@ -7304,8 +7195,8 @@ }, { "Name": "Cube (24)", - "ObjectId": -10276, - "ParentId": -10116, + "ObjectId": -2454, + "ParentId": -2122, "Position": { "x": 0.9594002, "y": -0.070599556, @@ -7329,8 +7220,8 @@ }, { "Name": "Cube (27)", - "ObjectId": -10278, - "ParentId": -10116, + "ObjectId": -2456, + "ParentId": -2122, "Position": { "x": 1.01130009, "y": -0.2470007, @@ -7354,8 +7245,8 @@ }, { "Name": "Cube (28)", - "ObjectId": -10280, - "ParentId": -10116, + "ObjectId": -2458, + "ParentId": -2122, "Position": { "x": 0.9963999, "y": -0.3125, @@ -7379,8 +7270,8 @@ }, { "Name": "Cube (29)", - "ObjectId": -10282, - "ParentId": -10116, + "ObjectId": -2460, + "ParentId": -2122, "Position": { "x": 0.973100662, "y": -0.352000237, @@ -7404,8 +7295,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -10284, - "ParentId": -10116, + "ObjectId": -2462, + "ParentId": -2122, "Position": { "x": 0.935500145, "y": -0.3800001, @@ -7429,8 +7320,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -10286, - "ParentId": -10116, + "ObjectId": -2464, + "ParentId": -2122, "Position": { "x": 0.8803005, "y": -0.402899742, @@ -7454,8 +7345,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10288, - "ParentId": -10116, + "ObjectId": -2466, + "ParentId": -2122, "Position": { "x": 0.814100266, "y": 0.381999969, @@ -7479,8 +7370,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -10290, - "ParentId": -10116, + "ObjectId": -2468, + "ParentId": -2122, "Position": { "x": 0.9194002, "y": -0.0346002579, @@ -7504,8 +7395,8 @@ }, { "Name": "Cube (17)", - "ObjectId": -10292, - "ParentId": -10116, + "ObjectId": -2470, + "ParentId": -2122, "Position": { "x": 0.6529999, "y": 0.340899467, @@ -7529,8 +7420,8 @@ }, { "Name": "Cube (18)", - "ObjectId": -10294, - "ParentId": -10116, + "ObjectId": -2472, + "ParentId": -2122, "Position": { "x": 0.6122999, "y": 0.291399956, @@ -7554,8 +7445,8 @@ }, { "Name": "Cube (24)", - "ObjectId": -10296, - "ParentId": -10116, + "ObjectId": -2474, + "ParentId": -2122, "Position": { "x": 0.7930002, "y": 0.0, @@ -7579,8 +7470,8 @@ }, { "Name": "Cube (21)", - "ObjectId": -10298, - "ParentId": -10116, + "ObjectId": -2476, + "ParentId": -2122, "Position": { "x": 0.606600761, "y": 0.127099991, @@ -7604,8 +7495,8 @@ }, { "Name": "Cube (22)", - "ObjectId": -10300, - "ParentId": -10116, + "ObjectId": -2478, + "ParentId": -2122, "Position": { "x": 0.6391001, "y": 0.0616998672, @@ -7629,8 +7520,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -10302, - "ParentId": -10116, + "ObjectId": -2480, + "ParentId": -2122, "Position": { "x": 0.6988001, "y": 0.37239933, @@ -7654,8 +7545,8 @@ }, { "Name": "Cube (19)", - "ObjectId": -10304, - "ParentId": -10116, + "ObjectId": -2482, + "ParentId": -2122, "Position": { "x": 0.5984001, "y": 0.2528, @@ -7679,8 +7570,8 @@ }, { "Name": "Cube (20)", - "ObjectId": -10306, - "ParentId": -10116, + "ObjectId": -2484, + "ParentId": -2122, "Position": { "x": 0.595399857, "y": 0.179800034, @@ -7704,8 +7595,8 @@ }, { "Name": "Cube (23)", - "ObjectId": -10308, - "ParentId": -10116, + "ObjectId": -2486, + "ParentId": -2122, "Position": { "x": 0.665500641, "y": 0.03489971, @@ -7729,8 +7620,8 @@ }, { "Name": "Cube (33)", - "ObjectId": -10310, - "ParentId": -10116, + "ObjectId": -2488, + "ParentId": -2122, "Position": { "x": 0.7663002, "y": -0.406899452, @@ -7754,8 +7645,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -10312, - "ParentId": -10116, + "ObjectId": -2490, + "ParentId": -2122, "Position": { "x": 0.5892, "y": -0.3327999, @@ -7779,8 +7670,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -10314, - "ParentId": -10116, + "ObjectId": -2492, + "ParentId": -2122, "Position": { "x": 0.6669998, "y": -0.4038, @@ -7804,8 +7695,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -10316, - "ParentId": -10116, + "ObjectId": -2494, + "ParentId": -2122, "Position": { "x": 0.6293001, "y": -0.377699852, @@ -7829,8 +7720,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -10318, - "ParentId": -10116, + "ObjectId": -2496, + "ParentId": -2122, "Position": { "x": 0.9555006, "y": 0.3522005, @@ -7854,8 +7745,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -10320, - "ParentId": -10116, + "ObjectId": -2498, + "ParentId": -2122, "Position": { "x": 0.91779995, "y": 0.3782997, @@ -7879,8 +7770,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -10322, - "ParentId": -10116, + "ObjectId": -2500, + "ParentId": -2122, "Position": { "x": 0.9956007, "y": 0.3072996, @@ -7903,9 +7794,34 @@ } }, { - "Name": "DeathParty", - "ObjectId": -10118, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2502, + "ParentId": -2122, + "Position": { + "x": -0.0729999542, + "y": -2.2010994, + "z": -0.7200031 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Airstrike Party", + "ObjectId": -2124, + "ParentId": -2088, "Position": { "x": -5.0, "y": 10.6, @@ -7920,8 +7836,8 @@ }, { "Name": "Sphere", - "ObjectId": -10628, - "ParentId": -10118, + "ObjectId": -2860, + "ParentId": -2124, "Position": { "x": 0.0, "y": 0.0, @@ -7945,8 +7861,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10630, - "ParentId": -10118, + "ObjectId": -2862, + "ParentId": -2124, "Position": { "x": -0.0254993439, "y": 0.418000221, @@ -7970,8 +7886,8 @@ }, { "Name": "Cube", - "ObjectId": -10632, - "ParentId": -10118, + "ObjectId": -2864, + "ParentId": -2124, "Position": { "x": 0.528500557, "y": 0.1409998, @@ -7995,8 +7911,8 @@ }, { "Name": "Cube", - "ObjectId": -10634, - "ParentId": -10118, + "ObjectId": -2866, + "ParentId": -2124, "Position": { "x": -0.0209999084, "y": 0.7340002, @@ -8020,8 +7936,8 @@ }, { "Name": "Cube", - "ObjectId": -10636, - "ParentId": -10118, + "ObjectId": -2868, + "ParentId": -2124, "Position": { "x": 0.3720007, "y": 0.5475006, @@ -8045,8 +7961,8 @@ }, { "Name": "Cube", - "ObjectId": -10638, - "ParentId": -10118, + "ObjectId": -2870, + "ParentId": -2124, "Position": { "x": -0.0418000221, "y": 0.881500244, @@ -8068,10 +7984,35 @@ "Color": "000000FF" } }, + { + "Name": "Platform", + "ObjectId": -2872, + "ParentId": -2124, + "Position": { + "x": 0.0, + "y": -2.5211, + "z": 0.0240001678 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, { "Name": "FallDown", - "ObjectId": -10120, - "ParentId": -9886, + "ObjectId": -2126, + "ParentId": -2088, "Position": { "x": 5.0, "y": 10.2261181, @@ -8086,8 +8027,8 @@ }, { "Name": "Quad", - "ObjectId": -10402, - "ParentId": -10120, + "ObjectId": -2606, + "ParentId": -2126, "Position": { "x": 0.0, "y": 0.0, @@ -8111,8 +8052,8 @@ }, { "Name": "Quad (1)", - "ObjectId": -10404, - "ParentId": -10120, + "ObjectId": -2608, + "ParentId": -2126, "Position": { "x": 0.0, "y": 0.0, @@ -8136,8 +8077,8 @@ }, { "Name": "Quad (2)", - "ObjectId": -10406, - "ParentId": -10120, + "ObjectId": -2610, + "ParentId": -2126, "Position": { "x": 0.0, "y": 0.0, @@ -8161,8 +8102,8 @@ }, { "Name": "Quad (3)", - "ObjectId": -10408, - "ParentId": -10120, + "ObjectId": -2612, + "ParentId": -2126, "Position": { "x": 0.0, "y": 0.0, @@ -8185,9 +8126,34 @@ } }, { - "Name": "Zombie3", - "ObjectId": -10122, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2614, + "ParentId": -2126, + "Position": { + "x": 0.0, + "y": -2.14721775, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Zombie Escape", + "ObjectId": -2128, + "ParentId": -2088, "Position": { "x": 10.0300007, "y": 8.0789, @@ -8202,8 +8168,8 @@ }, { "Name": "Z", - "ObjectId": -10644, - "ParentId": -10122, + "ObjectId": -2878, + "ParentId": -2128, "Position": { "x": 0.859999657, "y": 1.97709942, @@ -8218,8 +8184,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -11298, - "ParentId": -10644, + "ObjectId": -3290, + "ParentId": -2878, "Position": { "x": 0.0, "y": -0.01309998, @@ -8243,8 +8209,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -11300, - "ParentId": -10644, + "ObjectId": -3292, + "ParentId": -2878, "Position": { "x": 0.0, "y": -0.4076, @@ -8268,8 +8234,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -11302, - "ParentId": -10644, + "ObjectId": -3294, + "ParentId": -2878, "Position": { "x": 0.0, "y": 0.381, @@ -8293,8 +8259,8 @@ }, { "Name": "M", - "ObjectId": -10646, - "ParentId": -10122, + "ObjectId": -2880, + "ParentId": -2128, "Position": { "x": -0.0410003662, "y": 1.97709942, @@ -8309,8 +8275,8 @@ }, { "Name": "Cube (12)", - "ObjectId": -11330, - "ParentId": -10646, + "ObjectId": -3300, + "ParentId": -2880, "Position": { "x": 0.308, "y": -0.012900006, @@ -8334,8 +8300,8 @@ }, { "Name": "Cube (14)", - "ObjectId": -11332, - "ParentId": -10646, + "ObjectId": -3302, + "ParentId": -2880, "Position": { "x": 0.154, "y": 0.0920999944, @@ -8359,8 +8325,8 @@ }, { "Name": "Cube (13)", - "ObjectId": -11334, - "ParentId": -10646, + "ObjectId": -3304, + "ParentId": -2880, "Position": { "x": -0.304, "y": -0.012900006, @@ -8384,8 +8350,8 @@ }, { "Name": "Cube (15)", - "ObjectId": -11336, - "ParentId": -10646, + "ObjectId": -3306, + "ParentId": -2880, "Position": { "x": -0.149999991, "y": 0.0920999944, @@ -8409,8 +8375,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -11338, - "ParentId": -10646, + "ObjectId": -3308, + "ParentId": -2880, "Position": { "x": 0.002, "y": -0.2324, @@ -8434,8 +8400,8 @@ }, { "Name": "3", - "ObjectId": -10648, - "ParentId": -10122, + "ObjectId": -2882, + "ParentId": -2128, "Position": { "x": -0.888, "y": 1.99699974, @@ -8450,8 +8416,8 @@ }, { "Name": "Cube (25)", - "ObjectId": -11752, - "ParentId": -10648, + "ObjectId": -3490, + "ParentId": -2882, "Position": { "x": -0.1849, "y": -0.1269, @@ -8475,8 +8441,8 @@ }, { "Name": "Cube (26)", - "ObjectId": -11754, - "ParentId": -10648, + "ObjectId": -3492, + "ParentId": -2882, "Position": { "x": -0.2033, "y": -0.1894, @@ -8500,8 +8466,8 @@ }, { "Name": "Cube (24)", - "ObjectId": -11756, - "ParentId": -10648, + "ObjectId": -3494, + "ParentId": -2882, "Position": { "x": -0.153, "y": -0.073300004, @@ -8525,8 +8491,8 @@ }, { "Name": "Cube (27)", - "ObjectId": -11758, - "ParentId": -10648, + "ObjectId": -3496, + "ParentId": -2882, "Position": { "x": -0.2049, "y": -0.2497, @@ -8550,8 +8516,8 @@ }, { "Name": "Cube (28)", - "ObjectId": -11760, - "ParentId": -10648, + "ObjectId": -3498, + "ParentId": -2882, "Position": { "x": -0.19, "y": -0.3152, @@ -8575,8 +8541,8 @@ }, { "Name": "Cube (29)", - "ObjectId": -11762, - "ParentId": -10648, + "ObjectId": -3500, + "ParentId": -2882, "Position": { "x": -0.1667, "y": -0.3547, @@ -8600,8 +8566,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -11764, - "ParentId": -10648, + "ObjectId": -3502, + "ParentId": -2882, "Position": { "x": -0.1291, "y": -0.3827, @@ -8625,8 +8591,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -11766, - "ParentId": -10648, + "ObjectId": -3504, + "ParentId": -2882, "Position": { "x": -0.0739, "y": -0.405599982, @@ -8650,8 +8616,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -11768, - "ParentId": -10648, + "ObjectId": -3506, + "ParentId": -2882, "Position": { "x": -0.113000005, "y": -0.0373, @@ -8675,8 +8641,8 @@ }, { "Name": "Cube (33)", - "ObjectId": -11770, - "ParentId": -10648, + "ObjectId": -3508, + "ParentId": -2882, "Position": { "x": 0.0401, "y": -0.4096, @@ -8700,8 +8666,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -11772, - "ParentId": -10648, + "ObjectId": -3510, + "ParentId": -2882, "Position": { "x": 0.2172, "y": -0.335499972, @@ -8725,8 +8691,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -11774, - "ParentId": -10648, + "ObjectId": -3512, + "ParentId": -2882, "Position": { "x": 0.1394, "y": -0.4065, @@ -8750,8 +8716,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -11776, - "ParentId": -10648, + "ObjectId": -3514, + "ParentId": -2882, "Position": { "x": 0.1771, "y": -0.380399972, @@ -8775,8 +8741,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -11778, - "ParentId": -10648, + "ObjectId": -3516, + "ParentId": -2882, "Position": { "x": 0.0077, "y": 0.3793, @@ -8800,8 +8766,8 @@ }, { "Name": "Cube (17)", - "ObjectId": -11780, - "ParentId": -10648, + "ObjectId": -3518, + "ParentId": -2882, "Position": { "x": -0.1534, "y": 0.3382, @@ -8825,8 +8791,8 @@ }, { "Name": "Cube (18)", - "ObjectId": -11782, - "ParentId": -10648, + "ObjectId": -3520, + "ParentId": -2882, "Position": { "x": -0.1941, "y": 0.2887, @@ -8850,8 +8816,8 @@ }, { "Name": "Cube (24)", - "ObjectId": -11784, - "ParentId": -10648, + "ObjectId": -3522, + "ParentId": -2882, "Position": { "x": -0.042, "y": -0.00270000054, @@ -8875,8 +8841,8 @@ }, { "Name": "Cube (21)", - "ObjectId": -11786, - "ParentId": -10648, + "ObjectId": -3524, + "ParentId": -2882, "Position": { "x": -0.1998, "y": 0.12439999, @@ -8900,8 +8866,8 @@ }, { "Name": "Cube (22)", - "ObjectId": -11788, - "ParentId": -10648, + "ObjectId": -3526, + "ParentId": -2882, "Position": { "x": -0.1673, "y": 0.059, @@ -8925,8 +8891,8 @@ }, { "Name": "Cube (16)", - "ObjectId": -11790, - "ParentId": -10648, + "ObjectId": -3528, + "ParentId": -2882, "Position": { "x": -0.107599996, "y": 0.3697, @@ -8950,8 +8916,8 @@ }, { "Name": "Cube (19)", - "ObjectId": -11792, - "ParentId": -10648, + "ObjectId": -3530, + "ParentId": -2882, "Position": { "x": -0.208, "y": 0.2501, @@ -8975,8 +8941,8 @@ }, { "Name": "Cube (20)", - "ObjectId": -11794, - "ParentId": -10648, + "ObjectId": -3532, + "ParentId": -2882, "Position": { "x": -0.21100001, "y": 0.177099988, @@ -9000,8 +8966,8 @@ }, { "Name": "Cube (23)", - "ObjectId": -11796, - "ParentId": -10648, + "ObjectId": -3534, + "ParentId": -2882, "Position": { "x": -0.1409, "y": 0.0321999975, @@ -9025,8 +8991,8 @@ }, { "Name": "Cube (30)", - "ObjectId": -11798, - "ParentId": -10648, + "ObjectId": -3536, + "ParentId": -2882, "Position": { "x": 0.1491, "y": 0.3495, @@ -9050,8 +9016,8 @@ }, { "Name": "Cube (31)", - "ObjectId": -11800, - "ParentId": -10648, + "ObjectId": -3538, + "ParentId": -2882, "Position": { "x": 0.1114, "y": 0.3756, @@ -9075,8 +9041,8 @@ }, { "Name": "Cube (32)", - "ObjectId": -11802, - "ParentId": -10648, + "ObjectId": -3540, + "ParentId": -2882, "Position": { "x": 0.189199984, "y": 0.3046, @@ -9099,9 +9065,34 @@ } }, { - "Name": "FinishWay", - "ObjectId": -10124, - "ParentId": -9886, + "Name": "Platform", + "ObjectId": -2884, + "ParentId": -2128, + "Position": { + "x": -0.0300006866, + "y": 0.0, + "z": 0.23500061 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } + }, + { + "Name": "Race", + "ObjectId": -2130, + "ParentId": -2088, "Position": { "x": -10.0, "y": 10.54, @@ -9116,8 +9107,8 @@ }, { "Name": "Cylinder", - "ObjectId": -10594, - "ParentId": -10124, + "ObjectId": -2814, + "ParentId": -2130, "Position": { "x": 0.0, "y": 0.0, @@ -9141,8 +9132,8 @@ }, { "Name": "Cylinder (1)", - "ObjectId": -10596, - "ParentId": -10124, + "ObjectId": -2816, + "ParentId": -2130, "Position": { "x": 0.0, "y": 0.0, @@ -9166,8 +9157,8 @@ }, { "Name": "Cylinder (2)", - "ObjectId": -10598, - "ParentId": -10124, + "ObjectId": -2818, + "ParentId": -2130, "Position": { "x": 0.0152997971, "y": 0.0, @@ -9188,6 +9179,31 @@ "PrimitiveType": 2, "Color": "FF1A00FF" } + }, + { + "Name": "Platform", + "ObjectId": -2820, + "ParentId": -2130, + "Position": { + "x": 0.0, + "y": -2.46109962, + "z": 0.0 + }, + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.5, + "y": 0.127054334, + "z": 1.5 + }, + "BlockType": 1, + "Properties": { + "PrimitiveType": 2, + "Color": "464646FF" + } } ] } \ No newline at end of file