예제 #1
0
 public override void StartClientSide(ICoreClientAPI api)
 {
     api.RegisterCommand(new DebugTreeCommand(api));
     api.RegisterCommand(new LangMatchDebugCommand(api));
     api.RegisterCommand(new LangListDebugCommand(api));
     api.RegisterCommand(new ModListClientCommand(api));
 }
예제 #2
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            ClientAPI = api;
            EventAPI  = ClientAPI.Event;
            Logger    = ClientAPI.Logger;

            LoadConfig();

            AliasCommler = new AliasCommandler(this);
            ClientAPI.RegisterCommand(AliasCommler);


            Editor = new GuiDialogAliasEditor(ClientAPI);
            ClientAPI.Gui.RegisterDialog(Editor);

            // ClientAPI.Input.RegisterHotKey("opencmeditor", "Open CommandMacro editor", GlKeys.O);
            // ClientAPI.Input.SetHotKeyHandler("opencmeditor", combo => {
            //  Editor.TryOpen();
            //  return true;
            // });

            Logger.Debug("Initializing aliases!");
            Player = ClientAPI.World.Player;
            AliasMan.InitAllAliases(ClientAPI);

            EventAPI.LeaveWorld += SaveConfig;
        }
예제 #3
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            capi         = api;
            configLoader = capi.ModLoader.GetModSystem <ConfigLoader>();
            config       = configLoader.Config;
            capi.RegisterCommand("lightutil", "Light Util", "[lightlevel|type|radius|alpha|red]", new ClientChatCommandDelegate(CmdLightUtil));

            id = api.World.RegisterGameTickListener(dt =>
            {
                EntityPlayer player = api.World.Player.Entity;

                if (player != null)
                {
                    api.World.RegisterGameTickListener(d =>
                    {
                        if (config.LightLevels)
                        {
                            LightHighlight(null, config.LightLevelType);
                        }
                        else
                        {
                            ClearLightLevelHighlights();
                        }
                    }, 100);

                    api.World.UnregisterGameTickListener(id);
                }
            }, 500);
        }
예제 #4
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;
            api.Event.BlockTexturesLoaded += LoadRawMeshes;
            api.Event.LevelFinalize       += () => api.Shader.ReloadShaders();

            api.RegisterCommand("obj", "", "", (p, a) =>
            {
                var bs      = api.World.Player.CurrentBlockSelection;
                var es      = api.World.Player.CurrentEntitySelection;
                string word = a.PopWord("object");

                if (bs != null)
                {
                    var asset = api.World.BlockAccessor.GetBlock(bs.Position).Shape.Base;
                    capi.Tesselator.TesselateShape(api.World.GetBlock(0), (api.TesselatorManager as ShapeTesselatorManager).shapes[asset], out MeshData mesh);
                    ConvertToObj(mesh, word);
                }
                else if (es != null)
                {
                    capi.Tesselator.TesselateShape(api.World.GetBlock(0), es.Entity.Properties.Client.LoadedShape, out MeshData mesh);
                    ConvertToObj(mesh, word);
                }
            });
        }
예제 #5
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;
            api.RegisterCommand("obj", "", "", (p, a) =>
            {
                var bs      = api.World.Player.CurrentBlockSelection;
                var es      = api.World.Player.CurrentEntitySelection;
                string word = a.PopWord("object");

                if (bs != null)
                {
                    var asset   = api.World.BlockAccessor.GetBlock(bs.Position).Shape.Base;
                    string name = asset.ToShortString().Replace("/", "-");
                    api.Tesselator.TesselateShape(api.World.GetBlock(0), (api.TesselatorManager as ShapeTesselatorManager).shapes[asset], out MeshData mesh);
                    MassFileExportSystem.toExport.Push(new ExportableMesh(mesh, Path.Combine(GamePaths.DataPath, name + ".obj"), name + ".obj"));
                }
                else if (es != null)
                {
                    Shape loadedShape = es.Entity.Properties.Client.LoadedShape;
                    var texPos        = es.Entity.Properties.Client.Renderer as ITexPositionSource;
                    if (texPos == null)
                    {
                        return;
                    }
                    api.Tesselator.TesselateShape("", loadedShape, out MeshData mesh, texPos);
                    MassFileExportSystem.toExport.Push(new ExportableMesh(mesh, Path.Combine(GamePaths.DataPath, es.Entity.Code.ToShortString() + ".obj"), es.Entity.Code.ToShortString() + ".obj"));
                }
        public WeatherSimulationLightning(ICoreAPI api, WeatherSystemBase weatherSys)
        {
            this.weatherSys = weatherSys;
            weatherSysc     = weatherSys as WeatherSystemClient;
            this.capi       = api as ICoreClientAPI;

            if (api.Side == EnumAppSide.Client)
            {
                LightningAmbient = new AmbientModifier().EnsurePopulated();

                capi.Ambient.CurrentModifiers["lightningambient"] = LightningAmbient;

                capi.Event.ReloadShader += LoadShader;
                LoadShader();

                capi.Event.RegisterRenderer(this, EnumRenderStage.Opaque, "lightning");

                capi.RegisterCommand("lntest", "", "", onCmdLineTest);
            }
            else
            {
                api.Event.RegisterGameTickListener(OnServerTick, 40, 3);

                (api as ICoreServerAPI).RegisterCommand("lntest", "", "", onCmdLineTestServer);
            }
        }
예제 #7
0
        public WorldEditClientHandler(ICoreClientAPI capi)
        {
            this.capi = capi;
            capi.RegisterCommand("we", "World edit toolbar", "", CmdEditClient);
            capi.Input.RegisterHotKey("worldedit", "World Edit", GlKeys.Tilde, HotkeyType.CreativeTool);
            capi.Input.SetHotKeyHandler("worldedit", OnHotkeyWorldEdit);
            capi.Event.LeaveWorld += Event_LeaveWorld;
            capi.Event.FileDrop   += Event_FileDrop;

            clientChannel =
                capi.Network.RegisterChannel("worldedit")
                .RegisterMessageType(typeof(RequestWorkSpacePacket))
                .RegisterMessageType(typeof(WorldEditWorkspace))
                .RegisterMessageType(typeof(ChangePlayerModePacket))
                .RegisterMessageType(typeof(CopyToClipboardPacket))
                .RegisterMessageType(typeof(SchematicJsonPacket))
                .SetMessageHandler <WorldEditWorkspace>(OnServerWorkspace)
                .SetMessageHandler <CopyToClipboardPacket>(OnClipboardCopy)
                .SetMessageHandler <SchematicJsonPacket>(OnReceivedSchematic)
            ;

            if (!capi.Settings.Int.Exists("schematicMaxUploadSizeKb"))
            {
                capi.Settings.Int["schematicMaxUploadSizeKb"] = 75;
            }
        }
예제 #8
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            renderer = new PlacementRenderer(api);
            api.Event.RegisterRenderer(renderer, EnumRenderStage.Opaque);
            api.RegisterCommand("pconfig", "Config Placement Preview System", "[enabled|textured]", (id, args) =>
            {
                WaypointUtilConfig config = api.ModLoader.GetModSystem <WaypointUtilSystem>().Config;
                string arg   = args.PopWord();
                bool?enabled = args.PopBool();
                switch (arg)
                {
                case "enabled":
                    config.PRShow = enabled ?? !config.PRShow;
                    api.ShowChatMessage("Block preview set to " + config.PRShow);
                    break;

                case "tinted":
                    config.PRTint = enabled ?? !config.PRTint;
                    api.ShowChatMessage("Block preview tinting set to " + config.PRTint);
                    break;

                default:
                    break;
                }
                api.ModLoader.GetModSystem <ConfigLoader>().SaveConfig();
            });
            api.Event.LevelFinalize += () => api.Shader.ReloadShaders();
        }
예제 #9
0
 // the vs mod loader uses this to start our mod for the client side
 public override void StartClientSide(ICoreClientAPI api)
 {
     // this creates a client side command called "hello" with the description "Says Hello!"
     api.RegisterCommand("hello", "Says hello!", "hello", (int groupId, CmdArgs cmdArgs) => {
         // this says hello! :)
         api.ShowChatMessage("Hello!");
     });
 }
예제 #10
0
        public GuiDialogWorldMap(OnViewChangedDelegate viewChanged, ICoreClientAPI capi) : base("", capi)
        {
            this.viewChanged = viewChanged;
            fullDialog       = ComposeDialog(EnumDialogType.Dialog);
            hudDialog        = ComposeDialog(EnumDialogType.HUD);

            capi.RegisterCommand("worldmapsize", "Set the size of the world map dialog", "width height", onCmdMapSize);
        }
예제 #11
0
 public override void StartClientSide(ICoreClientAPI api)
 {
     this.capi = api;
     api.RegisterCommand("notification", "creates client notification", "", (id, args) =>
     {
         string text = args.PopAll();
         text        = text.Length < 1 ? "Notification" : text;
         CreateNotification(text);
     });
 }
예제 #12
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            capi                  = api;
            allowSaving           = LoadConfig();
            ChunkPartGrabber.Seed = api.World.Seed;
            var spawnChunk = api.World.DefaultSpawnPosition.AsBlockPos.GetChunkPos(api.World.BlockAccessor);

            ChunkPartGrabber.SpawnPos = spawnChunk;

            api.RegisterCommand("vshudforcesave", "Force saves vshud user settings with the current settings state.", "", (a, b) => SaveConfig(true));
        }
예제 #13
0
        public override void StartClientSide(ICoreClientAPI capi)
        {
            this.capi     = capi;
            clientChannel =
                capi.Network.RegisterChannel("weather")
                .RegisterMessageType(typeof(WeatherState))
                .SetMessageHandler <WeatherState>(OnWeatherUpdate)
            ;

            capi.RegisterCommand("cdensity", "Set cloud density", "[density] (best values between -1 and 1)", cDensity);

            capi.RegisterCommand("clight", "Set global Cloud brightness", "global brightness (best values between 0 and 1)", cLight);
            //capi.RegisterCommand("crand", "Set large and small cloud noise.", "amp1 amp2 freq1 freq2  (best values between 0.5 and 20)", cRandom);
            capi.RegisterCommand("cviewdist", "Sets the cloud view distance. Will be reset when view distance in graphics settings are changed.", "dist (length in cloud tiles)", cTileLength);

            capi.RegisterCommand("weather", "Show current weather info", "", cmdWeatherClient);

            capi.Event.RegisterGameTickListener(OnGameTick, 50);
            capi.Event.LevelFinalize += InitWeatherSim;
            capi.Event.LeaveWorld    += () => (cloudRenderer as CloudRenderer)?.Dispose();
        }
예제 #14
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            capi         = api;
            configLoader = capi.ModLoader.GetModSystem <ConfigLoader>();
            config       = ConfigLoader.Config;
            capi.RegisterCommand("lightutil", "Light Util", "[lightlevel|type|radius|alpha|red]", new ClientChatCommandDelegate(CmdLightUtil));

            capi.Event.LevelFinalize += () =>
            {
                capi.InjectClientThread("LightUtil", 40, new LightUtilSystem(api.World as ClientMain, config));
            };
        }
예제 #15
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;

            api.RegisterCommand("errorreporter", "Reopens the error reporting dialog", "[on|off]", ClientCmdErrorRep);

            api.Event.LevelFinalize += OnClientReady;
            api.Network.RegisterChannel("errorreporter")
            .RegisterMessageType(typeof(ServerLogEntries))
            .SetMessageHandler <ServerLogEntries>(OnServerLogEntriesReceived)
            ;
        }
예제 #16
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;

            capi.Network.RegisterChannel("VSHUD.Notification").RegisterMessageType <AssetLocation>().SetMessageHandler <AssetLocation>((a) =>
            {
                try
                {
                    string notification = a.ToShortString();
                    CreateNotification(notification);
                }
                catch (Exception)
                {
                    CreateNotification("Tried Parsing Bad Notification Packet, Ignoring.");
                }
            });

            //move to separate thread at some point
            id = api.Event.RegisterGameTickListener((dt) =>
            {
                if (IncomingNotifications.Count > 0)
                {
                    if (Notifications.Count < maxElements)
                    {
                        for (int i = 0; i < maxElements - Notifications.Count; i++)
                        {
                            if (i > IncomingNotifications.Count)
                            {
                                break;
                            }

                            var notif = IncomingNotifications.Dequeue();
                            var elem  = new HudElementNotification(api, notif.text, notif.color, notif.expiryTime - dt);
                            Notifications.Enqueue(elem);
                        }
                    }
                    else
                    {
                        //yea
                        Notifications.First().expiryTime = -0.1f;
                    }
                }
            }, 30);

            api.RegisterCommand("notification", "creates client notification", "", (id, args) =>
            {
                string text = args.PopAll();
                text        = text.Length < 1 ? "Notification" : text;
                CreateNotification(text);
            });
        }
예제 #17
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;

            api.RegisterCommand("csc", ConstantsCore.ModPrefix + "Clear shapes cache", "", (int groupId, CmdArgs args) =>
            {
                api.ObjectCache.RemoveAll((str, obj) => str.StartsWith(ConstantsCore.ModId));
            });

            // TODO Need move dialog to TPNetManager -.-
            api.RegisterCommand("tpdlg", ConstantsCore.ModPrefix + "Open teleport dialog", "", (int groupId, CmdArgs args) =>
            {
                if (capi.World.Player.WorldData.CurrentGameMode != EnumGameMode.Creative)
                {
                    return;
                }

                TPNetManager manager = api.ModLoader.GetModSystem <TPNetManager>();

                GuiDialogTeleport dialog = new GuiDialogTeleport(capi, null);
                dialog.TryOpen();
            });
        }
예제 #18
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;

            api.Network.GetChannel("charselection")
            .SetMessageHandler <CharacterSelectedState>(onSelectedState)
            ;

            api.Event.IsPlayerReady += Event_IsPlayerReady;
            api.Event.PlayerJoin    += Event_PlayerJoin;

            api.RegisterCommand("charsel", "", "", onCharSelCmd);

            api.Event.BlockTexturesLoaded += loadCharacterClasses;
        }
예제 #19
0
        public GuiDialogHandbook(ICoreClientAPI capi) : base(capi)
        {
            IPlayerInventoryManager invm = capi.World.Player.InventoryManager;

            capi.Settings.AddWatcher <float>("guiScale", (float val) => {
                initOverviewGui();
                foreach (GuiHandbookPage elem in shownHandbookPages)
                {
                    elem.Dispose();
                }
            });

            capi.RegisterCommand("reloadhandbook", "Reload handbook entries", "", cReload);
            loadEntries();
        }
예제 #20
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            api.RegisterCommand("fdcfg", "Floaty damage configuration", "state", (id, args) =>
            {
                switch (args.PopWord())
                {
                case "state":
                    ConfigLoader.Config.FDShow = args.PopBool() ?? !ConfigLoader.Config.FDShow;
                    api.ShowChatMessage(string.Format("Floaty Damage Hud Element Generation Set To {0}", ConfigLoader.Config.FDShow));
                    break;

                default:
                    break;
                }
                ConfigLoader.SaveConfig(api);
            });
        }
예제 #21
0
 private void RegisterTrigger(string trigger)
 {
     if (allTriggers.Contains(trigger))
     {
         return;
     }
     ClientAPI.RegisterCommand(trigger, Lang.Get("alias-command"), "", (group, args) => {
         var al = this[trigger];
         if (al is null)
         {
             return;
         }
         var allArgs = args.PopAllAsArray();
         AliasCommand(al, allArgs);
     });
     allTriggers.Add(trigger);
 }
예제 #22
0
        public GuiDialogEssence(ICoreClientAPI capi) : base(capi)
        {
            currentCatgoryCode = capi.Settings.String["currentHandbookCategoryCode"];

            IPlayerInventoryManager invm = capi.World.Player.InventoryManager;

            capi.Settings.AddWatcher <float>("guiScale", (float val) =>
            {
                initOverviewGui();
                foreach (GuiHandbookPage elem in shownEssencePages)
                {
                    elem.Dispose();
                }
            });

            capi.RegisterCommand("reloadessences", "Reload essence handbook entries", "", cReload);
            loadEntries();
        }
예제 #23
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            capi = api;

            api.RegisterCommand("clothtest", "", "", onClothTest);

            api.Event.RegisterRenderer(this, EnumRenderStage.Opaque, "clothsimu");

            api.Event.BlockTexturesLoaded += Event_BlockTexturesLoaded;

            api.Network.GetChannel("clothphysics")
            .SetMessageHandler <UnregisterClothSystemPacket>(onUnregPacketClient)
            .SetMessageHandler <ClothSystemPacket>(onRegPacketClient)
            .SetMessageHandler <ClothPointPacket>(onPointPacketClient)
            ;

            api.Event.LeaveWorld += Event_LeaveWorld;
        }
예제 #24
0
        public ProspectorOverlayLayer(ICoreAPI api, IWorldMapManager mapSink) : base(api, mapSink)
        {
            _worldMapManager = mapSink;
            _chunksize       = api.World.BlockAccessor.ChunkSize;
            _messages        = api.LoadOrCreateDataFile <ProspectorMessages>(Filename);
            _triggerwords    = LangUtils.GetAllLanguageStringsOfKey("propick-reading-title").Select(x => x.Split().FirstOrDefault()).Where(x => !string.IsNullOrEmpty(x)).ToArray();
            _cleanupRegex    = new Regex("<.*?>", RegexOptions.Compiled);

            var modSystem = this.api.ModLoader.GetModSystem <ProspectorInfoModSystem>();

            _config = modSystem.Config;

            if (api.Side == EnumAppSide.Client)
            {
                _clientApi = (ICoreClientAPI)api;
                _clientApi.Event.ChatMessage            += OnChatMessage;
                _clientApi.Event.AfterActiveSlotChanged += Event_AfterActiveSlotChanged;
                _clientApi.Event.PlayerJoin             += (p) =>
                {
                    if (p == _clientApi?.World.Player)
                    {
                        var invMan = p?.InventoryManager?.GetHotbarInventory();
                        invMan.SlotModified += Event_SlotModified;
                    }
                };
                _clientApi.Event.PlayerLeave += (p) =>
                {
                    if (p == _clientApi?.World.Player)
                    {
                        var invMan = p?.InventoryManager?.GetHotbarInventory();
                        invMan.SlotModified -= Event_SlotModified;
                    }
                };

                _clientApi.RegisterCommand("pi", "ProspectorInfo main command. Allows you to toggle the visibility of the chunk texture overlay.", "", OnPiCommand);

                _colorTexture?.Dispose();
                _colorTexture = GenerateOverlayTexture();
            }
        }
예제 #25
0
        public SystemCamStudio(ClientMain game) : base(game)
        {
            _game = game;
            _capi = (ICoreClientAPI)game.Api;

            InitModel();
            _platform = game.GetField <ClientPlatformAbstract>("Platform");

            _capi.UnregisterCommand("cam");
            _capi.RegisterCommand("cam", "Cinematic Camera Studio", "", CmdCam);

            var eventManager = game.GetField <ClientEventManager>("eventManager");

            eventManager.CallMethod("RegisterRenderer", new DummyRenderer {
                action = OnRenderFrame3D
            },
                                    EnumRenderStage.Opaque, "cinecam", 0.7f);
            eventManager.CallMethod("RegisterRenderer", new DummyRenderer {
                action = OnFinalizeFrame
            },
                                    EnumRenderStage.Done, "cinecam-done", 0.98f);
        }
예제 #26
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;

            api.Network.GetChannel("charselection")
            .SetMessageHandler <CharacterSelectedState>(onSelectedState)
            ;

            api.Event.IsPlayerReady += Event_IsPlayerReady;
            api.Event.PlayerJoin    += Event_PlayerJoin;

            api.RegisterCommand("charsel", "", "", onCharSelCmd);

            api.Event.BlockTexturesLoaded += loadCharacterClasses;


            charDlg = api.Gui.LoadedGuis.Find(dlg => dlg is GuiDialogCharacterBase) as GuiDialogCharacterBase;
            charDlg.Tabs.Add(new GuiTab()
            {
                Name = Lang.Get("charactertab-traits"), DataInt = 1
            });
            charDlg.RenderTabHandlers.Add(composeTraitsTab);
        }
예제 #27
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.clientSkinNetwork = new ClientSkinNetwork(api);

            api.Event.LevelFinalize += () =>
            {
                api.World.Player.Entity.WatchedAttributes.RegisterModifiedListener("race", () =>
                {
                    SetRacials(api.World.Player.Entity);
                });
                SetRacials(api.World.Player.Entity);
            };


            api.RegisterCommand("skin", "Opens skin change gui.", "", (int i, CmdArgs args) =>
            {
                GuiDialogSkin skinGui = new GuiDialogSkin(api, this.clientSkinNetwork);
                skinGui.TryOpen();
            });

            api.RegisterEntityRendererClass("CustomRenderer", typeof(EntityCharacterSkinRenderer));

            base.StartClientSide(api);
        }
예제 #28
0
 public override void StartClientSide(ICoreClientAPI api)
 {
     api.RegisterCommand(new CommandFloatyWaypoints(typeof(EnumCmdArgsFloatyWaypoints), api, api.ModLoader.GetModSystem <WaypointUtils>()));
 }
예제 #29
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            MacroManagerRef macroManager = new MacroManagerRef(api.MacroManager);

            api.RegisterCommand("addmacro", "adds macro from string", ".addmacro alt ctrl shift keycode secondkeycode^macroname^first command^second command^nth command", (a, args) =>
            {
                try
                {
                    string[] arguments = args.PopAll().Split('^');

                    string hotkey          = arguments.First();
                    List <string> commands = arguments.ToList();
                    commands.RemoveAt(0);

                    string code = commands.First();
                    commands.RemoveAt(0);

                    CmdArgs newArgs = new CmdArgs(hotkey);

                    macroManager.AddMacro(new Macro()
                    {
                        Code           = code,
                        Commands       = commands.ToArray(),
                        Index          = macroManager.MacroCount + 1,
                        KeyCombination = new KeyCombination()
                        {
                            Alt           = newArgs.PopBool() ?? false,
                            Ctrl          = newArgs.PopBool() ?? false,
                            Shift         = newArgs.PopBool() ?? false,
                            KeyCode       = (int)GetGlKey(ref newArgs),
                            SecondKeyCode = (int)GetGlKey(ref newArgs),
                        }
                    });
                }
                catch (Exception)
                {
                    api.World.Player.ShowChatNotification("Syntax: \".addmacro alt ctrl shift keycode secondkeycode^macroname^first command^second command^nth command\"");
                }
            });

            api.RegisterCommand("deletemacro", "deletes macro with the specified index", ".deletemacro (index)", (a, args) =>
            {
                int?index = args.PopInt();
                if (index != null)
                {
                    macroManager.DeleteMacro((int)index);
                }
                else
                {
                    api.World.Player.ShowChatNotification("syntax: \".deletemacro (index)\"");
                }
            });

            api.RegisterCommand("listmacros", "lists registered macros", "", (a, args) =>
            {
                StringBuilder stringBuilder = new StringBuilder("Macros:").AppendLine();

                int i = 1;

                foreach (var macro in macroManager.Macros)
                {
                    stringBuilder.Append(string.Format("{0}: {1}", macro.Key, macro.Value.Name));
                    if (i <= macroManager.MacroCount - 1)
                    {
                        stringBuilder.AppendLine();
                    }
                    i++;
                }
                api.World.Player.ShowChatNotification(stringBuilder.ToString());
            });
        }
예제 #30
0
        public override void StartClientSide(ICoreClientAPI api)
        {
            this.capi = api;
            api.RegisterCommand("obj", "", "", (p, a) =>
            {
                var bs = api.World.Player.CurrentBlockSelection;
                var es = api.World.Player.CurrentEntitySelection;

                MeshData mesh = null;
                string name   = a.PopWord();

                if (bs != null)
                {
                    var asset = api.World.BlockAccessor.GetBlock(bs.Position).Shape.Base;
                    name      = name ?? asset.GetSafeName();

                    api.Tesselator.TesselateShape(api.World.GetBlock(0), (api.TesselatorManager as ShapeTesselatorManager).shapes[asset], out mesh);
                }
                else if (es != null)
                {
                    Shape loadedShape = es.Entity.Properties.Client.LoadedShape;
                    var texPos        = es.Entity.Properties.Client.Renderer as ITexPositionSource;
                    if (texPos == null)
                    {
                        return;
                    }

                    name = name ?? es.Entity.Code.GetSafeName();
                    api.Tesselator.TesselateShape("", loadedShape, out mesh, texPos);
                }

                if (mesh != null)
                {
                    lock (MassFileExportSystem.toExport)
                    {
                        MassFileExportSystem.toExport.Push(new ExportableMesh(mesh, Path.Combine(GamePaths.DataPath, name + ".obj"), name + ".obj"));
                    }
                }
            });

            api.RegisterCommand("objworld", "", "", (p, a) =>
            {
                string arg = a.PopWord("cache");
                switch (arg)
                {
                case "cache":
                    ConfigLoader.Config.CreateChunkObjs = a.PopBool() ?? !ConfigLoader.Config.CreateChunkObjs;
                    capi.ShowChatMessage(string.Format("Chunk Tesselator .obj Caching {0}.", ConfigLoader.Config.CreateChunkObjs ? "Enabled" : "Disabled"));
                    break;

                case "clear":
                    MassFileExportSystem.Clear <ExportableChunkPart>();
                    break;

                default:
                    break;
                }

                ConfigLoader.SaveConfig(capi);
            });

            api.RegisterCommand("meshdata", "", "", (p, a) =>
            {
                var bs = api.World.Player.CurrentBlockSelection;
                var es = api.World.Player.CurrentEntitySelection;

                string name = a.PopWord();

                MeshData mesh = null;

                if (bs != null)
                {
                    var asset = api.World.BlockAccessor.GetBlock(bs.Position).Shape.Base;
                    name      = name ?? asset.GetSafeName();

                    api.Tesselator.TesselateShape(api.World.GetBlock(0), (api.TesselatorManager as ShapeTesselatorManager).shapes[asset], out mesh);
                }
                else if (es != null)
                {
                    name = name ?? es.Entity.Code.GetSafeName();

                    api.Tesselator.TesselateShape(api.World.GetBlock(0), es.Entity.Properties.Client.LoadedShape, out mesh);
                }

                if (mesh != null)
                {
                    lock (MassFileExportSystem.toExport)
                    {
                        MassFileExportSystem.toExport.Push(new ExportableJsonObject(mesh, Path.Combine(GamePaths.DataPath, name)));
                    }
                }
            });
        }