diff --git a/MCGalaxy/Commands/CPE/CmdEnvironment.cs b/MCGalaxy/Commands/CPE/CmdEnvironment.cs index 5de90adc3..e61acac7e 100644 --- a/MCGalaxy/Commands/CPE/CmdEnvironment.cs +++ b/MCGalaxy/Commands/CPE/CmdEnvironment.cs @@ -52,7 +52,7 @@ public sealed class CmdEnvironment : Command2 if (!LevelInfo.Check(p, data.Rank, lvl, "set env settings of this level")) return; } - string[] args = message.SplitSpaces(); + string[] args = message.SplitSpaces(2); string opt = args[0], value = args.Length > 1 ? args[1] : ""; if (!Handle(p, lvl, opt, value, cfg, area)) { Help(p); } } diff --git a/MCGalaxy/Commands/Information/CmdMapInfo.cs b/MCGalaxy/Commands/Information/CmdMapInfo.cs index eae5d6c1e..9abb5797a 100644 --- a/MCGalaxy/Commands/Information/CmdMapInfo.cs +++ b/MCGalaxy/Commands/Information/CmdMapInfo.cs @@ -23,6 +23,7 @@ using MCGalaxy.Games; using MCGalaxy.Levels.IO; using MCGalaxy.Maths; +using MCGalaxy.Network; using BlockID = System.UInt16; namespace MCGalaxy.Commands.Info @@ -159,6 +160,9 @@ static IGame GetAssociatedGame(string map) p.Message("Fancy colors: &eLavaLight {0}, &eLampLight {1}", Color(cfg.LavaLightColor), Color(cfg.LampLightColor)); } + if (cfg.LightingMode != Packet.LightingMode.None) { + p.Message("Lighting Mode: &b{0}{1}", cfg.LightingMode, cfg.LightingModeLocked ? "&c locked" : ""); + } p.Message("Water level: &b{0}&S, Bedrock offset: &b{1}&S, Clouds height: &b{2}&S, Max fog distance: &b{3}", data.Get(EnvProp.EdgeLevel), data.Get(EnvProp.SidesOffset), data.Get(EnvProp.CloudsLevel), data.Get(EnvProp.MaxFog)); diff --git a/MCGalaxy/Levels/LevelConfig.cs b/MCGalaxy/Levels/LevelConfig.cs index 0ed08ec03..92c9be0d9 100644 --- a/MCGalaxy/Levels/LevelConfig.cs +++ b/MCGalaxy/Levels/LevelConfig.cs @@ -21,6 +21,7 @@ using MCGalaxy.Config; using MCGalaxy.Games; using MCGalaxy.Modules.Games.ZS; +using MCGalaxy.Network; using BlockID = System.UInt16; namespace MCGalaxy @@ -137,6 +138,11 @@ public abstract class EnvConfig [ConfigString("LampLightColor", "Env", "", true)] public string LampLightColor = ""; + [ConfigEnum("LightingMode", "Env", Packet.LightingMode.None, typeof(Packet.LightingMode))] + public Packet.LightingMode LightingMode; + [ConfigBool("LightingModeLocked", "Env", false)] + public bool LightingModeLocked = false; + public void ResetEnv() { // TODO: Rewrite using ConfigElement somehow Weather = ENV_USE_DEFAULT; @@ -163,6 +169,9 @@ public abstract class EnvConfig SkyboxColor = ""; LavaLightColor = ""; LampLightColor = ""; + + LightingMode = Packet.LightingMode.None; + LightingModeLocked = false; } internal const int ENV_COLOR_COUNT = 7; diff --git a/MCGalaxy/Levels/LevelEnv.cs b/MCGalaxy/Levels/LevelEnv.cs index 2352d75b1..f058b028d 100644 --- a/MCGalaxy/Levels/LevelEnv.cs +++ b/MCGalaxy/Levels/LevelEnv.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; using MCGalaxy.Commands; +using MCGalaxy.Network; using BlockID = System.UInt16; namespace MCGalaxy { @@ -50,6 +51,8 @@ public static class EnvOptions { new EnvOption("Skybox", SetSkybox, "&HSets color of the skybox (default FFFFFF)"), new EnvOption("LavaLight", SetLavaLight, "&HSets color cast by bright natural blocks when fancy lighting is enabled (default FFEBC6)"), new EnvOption("LampLight", SetLampLight, "&HSets color cast by bright artificial blocks when fancy lighting is enabled (default FFFFFF)"), + new EnvOption("LightingMode", SetLightingMode, "&HSets the lighting mode, which can be Classic or Fancy. " + + "Add \"locked\" on the end to lock the mode. For example: &Tlightingmode classic locked"), new EnvOption("CloudsSpeed", SetCloudsSpeed, "&HSets how fast clouds move (negative moves in opposite direction)"), new EnvOption("WeatherSpeed", SetWeatherSpeed, "&HSets how fast rain/snow falls (negative falls upwards)"), new EnvOption("WeatherFade", SetWeatherFade, "&HSets how quickly rain/snow fades out over distance"), @@ -75,6 +78,7 @@ public static class EnvOptions { if (opt.CaselessEq("SkyboxVer")) opt = "SkyboxVerSpeed"; if (opt.CaselessEq("lavacolor")) opt = "LavaLight"; if (opt.CaselessEq("lampcolor")) opt = "LampLight"; + if (opt.CaselessEq("lighting")) opt = "LightingMode"; foreach (EnvOption option in Options) { if (option.Name.CaselessEq(opt)) return option; @@ -127,6 +131,16 @@ public static class EnvOptions { static void SetLampLight(Player p, string area, EnvConfig cfg, string value) { SetColor(p, value, area, "block lamp light color", ref cfg.LampLightColor); } + static void SetLightingMode(Player p, string area, EnvConfig cfg, string value) { + string[] args = value.SplitSpaces(2); + string lightingMode = args[0]; + bool locked = args.Length > 1 && args[1].CaselessEq("locked"); + + if (!SetEnum(p, lightingMode, area, "lighting mode", Packet.LightingMode.None, ref cfg.LightingMode)) return; + cfg.LightingModeLocked = locked; + if (locked) p.Message("Lighting mode for {0}&S was %clocked%S. Players will not be able to change lighting mode while inside.", area); + if (!p.Supports(CpeExt.LightingMode)) p.Message("&WNote: Your client does not support lighting modes, so you will see no changes."); + } static void SetCloudsSpeed(Player p, string area, EnvConfig cfg, string value) { SetFloat(p, value, area, 256, "clouds speed", ref cfg.CloudsSpeed, -0xFFFFFF, 0xFFFFFF); @@ -240,5 +254,17 @@ public static class EnvOptions { target = Utils.Hex(rgb.R, rgb.G, rgb.B); } } + + static bool SetEnum(Player p, string input, string area, string variable, T resetValue, ref T target) where T : struct { + if (IsResetString(input)) { + p.Message("Reset {0} for {1} &Sto normal", variable, area); + target = resetValue; + return true; + } else { + if (!CommandParser.GetEnum(p, input, variable, ref target)) return false; + p.Message("Set {0} for {1} &Sto {2}", variable, area, target.ToString()); + return true; + } + } } } \ No newline at end of file diff --git a/MCGalaxy/Network/CPESupport.cs b/MCGalaxy/Network/CPESupport.cs index 494856034..71da3dcaa 100644 --- a/MCGalaxy/Network/CPESupport.cs +++ b/MCGalaxy/Network/CPESupport.cs @@ -92,6 +92,7 @@ public class CpeExt public const string CustomModels = "CustomModels"; public const string PluginMessages = "PluginMessages"; public const string ExtEntityTeleport = "ExtEntityTeleport"; + public const string LightingMode = "LightingMode"; } public sealed class CpeExtension @@ -151,6 +152,7 @@ public sealed class CpeExtension new CpeExtension(CpeExt.CustomModels, "Allows defining custom models for entities", 2), new CpeExtension(CpeExt.PluginMessages, "Allows sending and receiving plugin messages from clients"), new CpeExtension(CpeExt.ExtEntityTeleport, "Allows sending more precisely controlled teleports"), + new CpeExtension(CpeExt.LightingMode, "Allows changing how the client lights worlds"), #if TEN_BIT_BLOCKS new CpeExtension(CpeExt.ExtBlocks, "Allows using block IDs over 255 in block definitions"), #endif diff --git a/MCGalaxy/Network/Packets/Opcode.cs b/MCGalaxy/Network/Packets/Opcode.cs index 4a695690e..7887a6227 100644 --- a/MCGalaxy/Network/Packets/Opcode.cs +++ b/MCGalaxy/Network/Packets/Opcode.cs @@ -78,5 +78,6 @@ public static class Opcode { public const byte CpeUndefineModel = 52; public const byte CpePluginMessage = 53; public const byte CpeEntityTeleportExt = 54; + public const byte CpeLightingMode = 55; } } diff --git a/MCGalaxy/Network/Packets/Packet.cs b/MCGalaxy/Network/Packets/Packet.cs index 5d05ced05..2b1e6d440 100644 --- a/MCGalaxy/Network/Packets/Packet.cs +++ b/MCGalaxy/Network/Packets/Packet.cs @@ -681,6 +681,15 @@ public enum TeleportMoveMode { AbsoluteInstant, AbsoluteSmooth, RelativeSmooth, buffer[4 + offset] = rot.HeadX; return buffer; } + + public enum LightingMode { None, Classic, Fancy } + public static byte[] SetLightingMode(LightingMode mode, bool locked) { + byte[] buffer = new byte[3]; + buffer[0] = Opcode.CpeLightingMode; + buffer[1] = (byte)mode; + buffer[2] = (byte)(locked ? 1 : 0); + return buffer; + } #endregion diff --git a/MCGalaxy/Player/Player.Handlers.cs b/MCGalaxy/Player/Player.Handlers.cs index 15c647710..cb3e8c1c4 100644 --- a/MCGalaxy/Player/Player.Handlers.cs +++ b/MCGalaxy/Player/Player.Handlers.cs @@ -316,6 +316,21 @@ public partial class Player : IDisposable Send(Packet.EnvMapProperty(i, value)); } } + if (Supports(CpeExt.LightingMode)) { + EnvConfig cfg; + if (zone != null && zone.Config.LightingMode != Packet.LightingMode.None) { + // Zone takes most precedence if it has a setting + cfg = zone.Config; + } else { + if (level.Config.LightingMode == Packet.LightingMode.None) { + // If level has no setting, use global + cfg = Server.Config; + } else { + cfg = level.Config; + } + } + Send(Packet.SetLightingMode(cfg.LightingMode, cfg.LightingModeLocked)); + } int weather = CurrentEnvProp(EnvProp.Weather, zone); Session.SendSetWeather((byte)weather);