diff --git a/ClassicalSharp/2D/GuiElement.cs b/ClassicalSharp/2D/GuiElement.cs
index 28b3fd27c..b32c93745 100644
--- a/ClassicalSharp/2D/GuiElement.cs
+++ b/ClassicalSharp/2D/GuiElement.cs
@@ -43,7 +43,7 @@ namespace ClassicalSharp.Gui {
public abstract class Screen : GuiElement {
public Screen(Game game) : base(game) { }
- public bool HandlesAllInput, BlocksWorld, HidesHud, RenderHudOver;
+ public bool HandlesAllInput = true, BlocksWorld, HidesHud, RenderHudOver;
public abstract void OnResize();
protected abstract void ContextLost();
diff --git a/ClassicalSharp/2D/Screens/ChatScreen.cs b/ClassicalSharp/2D/Screens/ChatScreen.cs
index 955fe9811..a55ede99d 100644
--- a/ClassicalSharp/2D/Screens/ChatScreen.cs
+++ b/ClassicalSharp/2D/Screens/ChatScreen.cs
@@ -14,6 +14,7 @@ namespace ClassicalSharp.Gui.Screens {
public ChatScreen(Game game, HudScreen hud) : base(game) {
chatLines = game.ChatLines;
this.hud = hud;
+ HandlesAllInput = false;
}
HudScreen hud;
@@ -275,7 +276,6 @@ namespace ClassicalSharp.Gui.Screens {
protected override void ContextLost() {
if (HandlesAllInput) {
chatInInputBuffer = input.Text.ToString();
- game.CursorVisible = false;
} else {
chatInInputBuffer = null;
}
@@ -330,7 +330,6 @@ namespace ClassicalSharp.Gui.Screens {
}
public void OpenInput(string initialText) {
- game.CursorVisible = true;
suppressNextPress = true;
SetHandlesAllInput(true);
Keyboard.KeyRepeat = true;
@@ -350,9 +349,6 @@ namespace ClassicalSharp.Gui.Screens {
if (HandlesAllInput) { // text input bar
if (key == game.Mapping(KeyBind.SendChat) || key == Key.KeypadEnter || key == game.Mapping(KeyBind.PauseOrExit)) {
SetHandlesAllInput(false);
- // when underlying screen is HUD, user is interacting with the world normally
- game.CursorVisible = game.Gui.UnderlyingScreen != game.Gui.hudScreen;
- game.Camera.RegrabMouse();
Keyboard.KeyRepeat = false;
if (key == game.Mapping(KeyBind.PauseOrExit))
@@ -466,6 +462,7 @@ namespace ClassicalSharp.Gui.Screens {
void SetHandlesAllInput(bool handles) {
HandlesAllInput = handles;
game.Gui.hudScreen.HandlesAllInput = handles;
+ game.Gui.CalcCursorVisible();
}
}
}
\ No newline at end of file
diff --git a/ClassicalSharp/2D/Screens/DisconnectScreen.cs b/ClassicalSharp/2D/Screens/DisconnectScreen.cs
index e34755782..62b3bb5d0 100644
--- a/ClassicalSharp/2D/Screens/DisconnectScreen.cs
+++ b/ClassicalSharp/2D/Screens/DisconnectScreen.cs
@@ -25,7 +25,6 @@ namespace ClassicalSharp.Gui.Screens {
messageFont = new Font(game.FontName, 16);
BlocksWorld = true;
HidesHud = true;
- HandlesAllInput = true;
}
public override void Init() {
diff --git a/ClassicalSharp/2D/Screens/HudScreen.cs b/ClassicalSharp/2D/Screens/HudScreen.cs
index 348f5ed75..cb59b2f3c 100644
--- a/ClassicalSharp/2D/Screens/HudScreen.cs
+++ b/ClassicalSharp/2D/Screens/HudScreen.cs
@@ -8,7 +8,9 @@ using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
public class HudScreen : Screen, IGameComponent {
- public HudScreen(Game game) : base(game) { }
+ public HudScreen(Game game) : base(game) {
+ HandlesAllInput = false;
+ }
ChatScreen chat;
internal Widget hotbar;
diff --git a/ClassicalSharp/2D/Screens/InventoryScreen.cs b/ClassicalSharp/2D/Screens/InventoryScreen.cs
index f54379a3c..da9f5cc1c 100644
--- a/ClassicalSharp/2D/Screens/InventoryScreen.cs
+++ b/ClassicalSharp/2D/Screens/InventoryScreen.cs
@@ -5,13 +5,24 @@ using ClassicalSharp.Gui.Widgets;
using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
- public partial class InventoryScreen : Screen {
+ public class InventoryScreen : Screen {
TableWidget table;
Font font;
+ bool deferredSelect;
public InventoryScreen(Game game) : base(game) {
font = new Font(game.FontName, 16);
- HandlesAllInput = true;
+ }
+
+ void MoveToSelected() {
+ table.SetBlockTo(game.Inventory.Selected);
+ table.Recreate();
+ deferredSelect = false;
+
+ // User is holding invalid block
+ if (table.SelectedIndex == -1) {
+ table.MakeDescTex(game.Inventory.Selected);
+ }
}
public override void Init() {
@@ -20,19 +31,22 @@ namespace ClassicalSharp.Gui.Screens {
table.ElementsPerRow = game.PureClassic ? 9 : 10;
table.Init();
- // User is holding invalid block
- if (table.SelectedIndex == -1) {
- table.MakeDescTex(game.Inventory.Selected);
- }
-
+ // Can't immediately move to selected here, because cursor visibility
+ // might be toggled after Init() is called. This causes the cursor to
+ // be moved back to the middle of the window.
+ deferredSelect = true;
+
game.Events.BlockPermissionsChanged += OnBlockChanged;
- game.Events.BlockDefinitionChanged += OnBlockChanged;
+ game.Events.BlockDefinitionChanged += OnBlockChanged;
Keyboard.KeyRepeat = true;
game.Graphics.ContextLost += ContextLost;
game.Graphics.ContextRecreated += ContextRecreated;
}
- public override void Render(double delta) { table.Render(delta); }
+ public override void Render(double delta) {
+ if (deferredSelect) MoveToSelected();
+ table.Render(delta);
+ }
public override void Dispose() {
font.Dispose();
diff --git a/ClassicalSharp/2D/Screens/LoadingMapScreen.cs b/ClassicalSharp/2D/Screens/LoadingMapScreen.cs
index 36b1bd377..c7bf67b68 100644
--- a/ClassicalSharp/2D/Screens/LoadingMapScreen.cs
+++ b/ClassicalSharp/2D/Screens/LoadingMapScreen.cs
@@ -21,7 +21,6 @@ namespace ClassicalSharp.Gui.Screens {
font = new Font(game.FontName, 16);
BlocksWorld = true;
RenderHudOver = true;
- HandlesAllInput = true;
}
string title, message;
diff --git a/ClassicalSharp/2D/Screens/Menu/ListScreen.cs b/ClassicalSharp/2D/Screens/Menu/ListScreen.cs
index 818a19099..c1fe0f35a 100644
--- a/ClassicalSharp/2D/Screens/Menu/ListScreen.cs
+++ b/ClassicalSharp/2D/Screens/Menu/ListScreen.cs
@@ -7,9 +7,7 @@ using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
public abstract class ListScreen : ClickableScreen {
- public ListScreen(Game game) : base(game) {
- HandlesAllInput = true;
- }
+ public ListScreen(Game game) : base(game) { }
protected Font font;
protected string[] entries;
diff --git a/ClassicalSharp/2D/Screens/Menu/MenuScreen.cs b/ClassicalSharp/2D/Screens/Menu/MenuScreen.cs
index 796bb4540..831a362f6 100644
--- a/ClassicalSharp/2D/Screens/Menu/MenuScreen.cs
+++ b/ClassicalSharp/2D/Screens/Menu/MenuScreen.cs
@@ -1,67 +1,65 @@
-// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
-using System;
-using System.Drawing;
-using OpenTK.Input;
-
-namespace ClassicalSharp.Gui.Screens {
- public abstract class MenuScreen : ClickableScreen {
-
- public MenuScreen(Game game) : base(game) {
- HandlesAllInput = true;
- }
-
- protected Widget[] widgets;
- protected Font titleFont, textFont;
- protected int IndexWidget(Widget w) { return IndexWidget(widgets, w); }
-
- public override void Render(double delta) {
- RenderMenuBounds();
- game.Graphics.Texturing = true;
- RenderWidgets(widgets, delta);
- game.Graphics.Texturing = false;
- }
-
- public override void Init() {
- if (titleFont == null) titleFont = new Font(game.FontName, 16, FontStyle.Bold);
- if (textFont == null) textFont = new Font(game.FontName, 16);
-
- game.Graphics.ContextLost += ContextLost;
- game.Graphics.ContextRecreated += ContextRecreated;
- }
-
- public override void Dispose() {
- ContextLost();
- if (titleFont != null) { titleFont.Dispose(); titleFont = null; }
- if (textFont != null) { textFont.Dispose(); textFont = null; }
-
- game.Graphics.ContextLost -= ContextLost;
- game.Graphics.ContextRecreated -= ContextRecreated;
- }
-
- protected override void ContextLost() { DisposeWidgets(widgets); }
-
- public override void OnResize() {
- RepositionWidgets(widgets);
- }
-
-
- public override bool HandlesMouseDown(int mouseX, int mouseY, MouseButton button) {
- return HandleMouseDown(widgets, mouseX, mouseY, button) >= 0;
- }
-
- public override bool HandlesMouseMove(int mouseX, int mouseY) {
- return HandleMouseMove(widgets, mouseX, mouseY) >= 0;
- }
- public override bool HandlesMouseScroll(float delta) { return true; }
-
- public override bool HandlesKeyDown(Key key) {
- if (key == Key.Escape) {
- game.Gui.SetNewScreen(null);
- return true;
- }
- return key < Key.F1 || key > Key.F35;
- }
- public override bool HandlesKeyPress(char key) { return true; }
- public override bool HandlesKeyUp(Key key) { return true; }
- }
+// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
+using System;
+using System.Drawing;
+using OpenTK.Input;
+
+namespace ClassicalSharp.Gui.Screens {
+ public abstract class MenuScreen : ClickableScreen {
+
+ public MenuScreen(Game game) : base(game) { }
+
+ protected Widget[] widgets;
+ protected Font titleFont, textFont;
+ protected int IndexWidget(Widget w) { return IndexWidget(widgets, w); }
+
+ public override void Render(double delta) {
+ RenderMenuBounds();
+ game.Graphics.Texturing = true;
+ RenderWidgets(widgets, delta);
+ game.Graphics.Texturing = false;
+ }
+
+ public override void Init() {
+ if (titleFont == null) titleFont = new Font(game.FontName, 16, FontStyle.Bold);
+ if (textFont == null) textFont = new Font(game.FontName, 16);
+
+ game.Graphics.ContextLost += ContextLost;
+ game.Graphics.ContextRecreated += ContextRecreated;
+ }
+
+ public override void Dispose() {
+ ContextLost();
+ if (titleFont != null) { titleFont.Dispose(); titleFont = null; }
+ if (textFont != null) { textFont.Dispose(); textFont = null; }
+
+ game.Graphics.ContextLost -= ContextLost;
+ game.Graphics.ContextRecreated -= ContextRecreated;
+ }
+
+ protected override void ContextLost() { DisposeWidgets(widgets); }
+
+ public override void OnResize() {
+ RepositionWidgets(widgets);
+ }
+
+
+ public override bool HandlesMouseDown(int mouseX, int mouseY, MouseButton button) {
+ return HandleMouseDown(widgets, mouseX, mouseY, button) >= 0;
+ }
+
+ public override bool HandlesMouseMove(int mouseX, int mouseY) {
+ return HandleMouseMove(widgets, mouseX, mouseY) >= 0;
+ }
+ public override bool HandlesMouseScroll(float delta) { return true; }
+
+ public override bool HandlesKeyDown(Key key) {
+ if (key == Key.Escape) {
+ game.Gui.SetNewScreen(null);
+ return true;
+ }
+ return key < Key.F1 || key > Key.F35;
+ }
+ public override bool HandlesKeyPress(char key) { return true; }
+ public override bool HandlesKeyUp(Key key) { return true; }
+ }
}
\ No newline at end of file
diff --git a/ClassicalSharp/2D/Screens/StatusScreen.cs b/ClassicalSharp/2D/Screens/StatusScreen.cs
index 51ea3cc87..64fc07636 100644
--- a/ClassicalSharp/2D/Screens/StatusScreen.cs
+++ b/ClassicalSharp/2D/Screens/StatusScreen.cs
@@ -19,6 +19,7 @@ namespace ClassicalSharp.Gui.Screens {
public StatusScreen(Game game) : base(game) {
statusBuffer = new StringBuffer(128);
+ HandlesAllInput = false;
}
void IGameComponent.Init(Game game) { }
diff --git a/ClassicalSharp/2D/Widgets/TableWidget.cs b/ClassicalSharp/2D/Widgets/TableWidget.cs
index 6186f8194..6fc09bf2e 100644
--- a/ClassicalSharp/2D/Widgets/TableWidget.cs
+++ b/ClassicalSharp/2D/Widgets/TableWidget.cs
@@ -106,8 +106,6 @@ namespace ClassicalSharp.Gui.Widgets {
scroll = new ScrollbarWidget(game);
RecreateElements();
Reposition();
- SetBlockTo(game.Inventory.Selected);
- Recreate();
}
public override void Dispose() {
@@ -177,7 +175,7 @@ namespace ClassicalSharp.Gui.Widgets {
void MoveCursorToSelected() {
if (SelectedIndex == -1) return;
- game.DesktopCursorPos = GetMouseCoords(SelectedIndex);
+ game.window.DesktopCursorPos = GetMouseCoords(SelectedIndex);
}
void UpdateBlockInfoString(BlockID block) {
diff --git a/ClassicalSharp/Entities/Entity.cs b/ClassicalSharp/Entities/Entity.cs
index 82639d16c..1a15a300d 100644
--- a/ClassicalSharp/Entities/Entity.cs
+++ b/ClassicalSharp/Entities/Entity.cs
@@ -97,15 +97,12 @@ namespace ClassicalSharp.Entities {
return m;
}
- /// Gets the brightness colour of this entity.
public virtual PackedCol Colour() {
Vector3I P = Vector3I.Floor(EyePosition);
return game.World.IsValidPos(P) ? game.Lighting.LightCol(P.X, P.Y, P.Z) : game.Lighting.Outside;
}
- /// Sets the model associated with this entity.
- /// Can be either 'name' or 'name'|'scale'.
public void SetModel(string model) {
ModelScale = new Vector3(1.0f);
int sep = model.IndexOf('|');
diff --git a/ClassicalSharp/Game/Game.Properties.cs b/ClassicalSharp/Game/Game.Properties.cs
index 97418f9a0..4b9bfcd09 100644
--- a/ClassicalSharp/Game/Game.Properties.cs
+++ b/ClassicalSharp/Game/Game.Properties.cs
@@ -204,31 +204,7 @@ namespace ClassicalSharp {
}
}
- public INativeWindow window;
-
+ public INativeWindow window;
public int Width, Height;
-
- public bool Focused { get { return window.Focused; } }
-
- bool visible = true;
- internal bool realVisible = true;
- public bool CursorVisible {
- get { return visible; }
- set {
- // Defer mouse visibility changes.
- realVisible = value;
- if (Gui.overlays.Count > 0) return;
-
- // Only set the value when it has changes.
- if (visible == value) return;
- window.CursorVisible = value;
- visible = value;
- }
- }
-
- public Point DesktopCursorPos {
- get { return window.DesktopCursorPos; }
- set { window.DesktopCursorPos = value; }
- }
}
}
\ No newline at end of file
diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs
index e5fe82fe2..db99e72e8 100644
--- a/ClassicalSharp/Game/Game.cs
+++ b/ClassicalSharp/Game/Game.cs
@@ -306,7 +306,7 @@ namespace ClassicalSharp {
Vertices = 0;
Camera.UpdateMouse();
- if (!Focused && !Gui.ActiveScreen.HandlesAllInput) {
+ if (!window.Focused && !Gui.ActiveScreen.HandlesAllInput) {
Gui.SetNewScreen(new PauseScreen(this));
}
diff --git a/ClassicalSharp/Game/GuiInterface.cs b/ClassicalSharp/Game/GuiInterface.cs
index f2afba0b2..5fbe70597 100644
--- a/ClassicalSharp/Game/GuiInterface.cs
+++ b/ClassicalSharp/Game/GuiInterface.cs
@@ -84,41 +84,28 @@ namespace ClassicalSharp {
if (activeScreen != null && disposeOld)
activeScreen.Dispose();
- if (screen == null) {
- game.CursorVisible = false;
- if (game.Focused) game.Camera.RegrabMouse();
- } else if (activeScreen == null) {
- game.CursorVisible = true;
- }
-
- if (screen != null)
- screen.Init();
+ if (screen != null) screen.Init();
activeScreen = screen;
+ CalcCursorVisible();
}
public void RefreshHud() { hudScreen.Recreate(); }
public void ShowOverlay(Overlay overlay, bool inFront) {
- bool cursorVis = game.CursorVisible;
- if (overlays.Count == 0) game.CursorVisible = true;
-
if (inFront) {
overlays.Insert(0, overlay);
} else {
overlays.Add(overlay);
}
- if (overlays.Count == 1) game.CursorVisible = cursorVis;
- // Save cursor visibility state
+
overlay.Init();
+ CalcCursorVisible();
}
public void DisposeOverlay(Overlay overlay) {
overlay.Dispose();
overlays.Remove(overlay);
-
- if (overlays.Count == 0)
- game.CursorVisible = game.realVisible;
- game.Camera.RegrabMouse();
+ CalcCursorVisible();
}
@@ -144,5 +131,16 @@ namespace ClassicalSharp {
overlays[i].OnResize();
}
}
+
+ bool cursorVisible = true;
+ public void CalcCursorVisible() {
+ bool vis = ActiveScreen.HandlesAllInput;
+ if (vis == cursorVisible) return;
+ cursorVisible = vis;
+
+ game.window.CursorVisible = vis;
+ if (game.window.Focused)
+ game.Camera.RegrabMouse();
+ }
}
}
\ No newline at end of file
diff --git a/ClassicalSharp/GraphicsAPI/GL.cs b/ClassicalSharp/GraphicsAPI/GL.cs
index c78395fa0..a14ec7aa0 100644
--- a/ClassicalSharp/GraphicsAPI/GL.cs
+++ b/ClassicalSharp/GraphicsAPI/GL.cs
@@ -32,7 +32,7 @@ using OpenTK;
namespace OpenTK.Graphics.OpenGL {
[InteropPatch]
- public unsafe static partial class GL {
+ public unsafe static class GL {
public static void AlphaFunc(Compare func, float value) {
Interop.Calli((int)func, value, AlphaFuncAddress);
@@ -243,6 +243,83 @@ namespace OpenTK.Graphics.OpenGL {
public static void Viewport(int x, int y, int width, int height) {
Interop.Calli(x, y, width, height, ViewportAddress);
} static IntPtr ViewportAddress;
+
+
+ internal static void LoadEntryPoints(IGraphicsContext context) {
+ Debug.Print("Loading OpenGL function pointers... ");
+ AlphaFuncAddress = context.GetAddress("glAlphaFunc");
+
+ BeginAddress = context.GetAddress("glBegin");
+ BindBufferAddress = context.GetAddress("glBindBuffer");
+ BindBufferARBAddress = context.GetAddress("glBindBufferARB");
+ BindTextureAddress = context.GetAddress("glBindTexture");
+ BlendFuncAddress = context.GetAddress("glBlendFunc");
+ BufferDataAddress = context.GetAddress("glBufferData");
+ BufferDataARBAddress = context.GetAddress("glBufferDataARB");
+ BufferSubDataAddress = context.GetAddress("glBufferSubData");
+ BufferSubDataARBAddress = context.GetAddress("glBufferSubDataARB");
+
+ CallListAddress = context.GetAddress("glCallList");
+ ClearAddress = context.GetAddress("glClear");
+ ClearColorAddress = context.GetAddress("glClearColor");
+ Color4ubAddress = context.GetAddress("glColor4ub");
+ ColorMaskAddress = context.GetAddress("glColorMask");
+ ColorPointerAddress = context.GetAddress("glColorPointer");
+ CullFaceAddress = context.GetAddress("glCullFace");
+
+ DeleteBuffersAddress = context.GetAddress("glDeleteBuffers");
+ DeleteBuffersARBAddress = context.GetAddress("glDeleteBuffersARB");
+ DeleteListsAddress = context.GetAddress("glDeleteLists");
+ DeleteTexturesAddress = context.GetAddress("glDeleteTextures");
+ DepthFuncAddress = context.GetAddress("glDepthFunc");
+ DepthMaskAddress = context.GetAddress("glDepthMask");
+ DisableAddress = context.GetAddress("glDisable");
+ DisableClientStateAddress = context.GetAddress("glDisableClientState");
+ DrawArraysAddress = context.GetAddress("glDrawArrays");
+ DrawElementsAddress = context.GetAddress("glDrawElements");
+
+ EnableAddress = context.GetAddress("glEnable");
+ EnableClientStateAddress = context.GetAddress("glEnableClientState");
+ EndAddress = context.GetAddress("glEnd");
+ EndListAddress = context.GetAddress("glEndList");
+ FogfAddress = context.GetAddress("glFogf");
+ FogfvAddress = context.GetAddress("glFogfv");
+ FogiAddress = context.GetAddress("glFogi");
+
+ GenBuffersAddress = context.GetAddress("glGenBuffers");
+ GenBuffersARBAddress = context.GetAddress("glGenBuffersARB");
+ GenListsAddress = context.GetAddress("glGenLists");
+ GenTexturesAddress = context.GetAddress("glGenTextures");
+ GetErrorAddress = context.GetAddress("glGetError");
+ GetIntegervAddress = context.GetAddress("glGetIntegerv");
+ GetStringAddress = context.GetAddress("glGetString");
+ GetTexImageAddress = context.GetAddress("glGetTexImage");
+
+ HintAddress = context.GetAddress("glHint");
+ LoadIdentityAddress = context.GetAddress("glLoadIdentity");
+ LoadMatrixfAddress = context.GetAddress("glLoadMatrixf");
+ MatrixModeAddress = context.GetAddress("glMatrixMode");
+ MultMatrixfAddress = context.GetAddress("glMultMatrixf");
+ NewListAddress = context.GetAddress("glNewList");
+ ReadPixelsAddress = context.GetAddress("glReadPixels");
+
+ TexCoord2fAddress = context.GetAddress("glTexCoord2f");
+ TexCoordPointerAddress = context.GetAddress("glTexCoordPointer");
+ TexImage2DAddress = context.GetAddress("glTexImage2D");
+ TexParameteriAddress = context.GetAddress("glTexParameteri");
+ TexSubImage2DAddress = context.GetAddress("glTexSubImage2D");
+ Vertex3fAddress = context.GetAddress("glVertex3f");
+ VertexPointerAddress = context.GetAddress("glVertexPointer");
+ ViewportAddress = context.GetAddress("glViewport");
+ }
+
+ public static void UseArbVboAddresses() {
+ BindBufferAddress = BindBufferARBAddress;
+ BufferDataAddress = BufferDataARBAddress;
+ BufferSubDataAddress = BufferSubDataARBAddress;
+ DeleteBuffersAddress = DeleteBuffersARBAddress;
+ GenBuffersAddress = GenBuffersARBAddress;
+ }
}
public enum ArrayCap : int {
@@ -418,83 +495,5 @@ namespace OpenTK.Graphics.OpenGL {
public enum TextureTarget : int {
Texture2D = 0x0DE1,
}
-
- public unsafe static partial class GL {
- internal static void LoadEntryPoints(IGraphicsContext context) {
- Debug.Print("Loading OpenGL function pointers... ");
- AlphaFuncAddress = context.GetAddress("glAlphaFunc");
-
- BeginAddress = context.GetAddress("glBegin");
- BindBufferAddress = context.GetAddress("glBindBuffer");
- BindBufferARBAddress = context.GetAddress("glBindBufferARB");
- BindTextureAddress = context.GetAddress("glBindTexture");
- BlendFuncAddress = context.GetAddress("glBlendFunc");
- BufferDataAddress = context.GetAddress("glBufferData");
- BufferDataARBAddress = context.GetAddress("glBufferDataARB");
- BufferSubDataAddress = context.GetAddress("glBufferSubData");
- BufferSubDataARBAddress = context.GetAddress("glBufferSubDataARB");
-
- CallListAddress = context.GetAddress("glCallList");
- ClearAddress = context.GetAddress("glClear");
- ClearColorAddress = context.GetAddress("glClearColor");
- Color4ubAddress = context.GetAddress("glColor4ub");
- ColorMaskAddress = context.GetAddress("glColorMask");
- ColorPointerAddress = context.GetAddress("glColorPointer");
- CullFaceAddress = context.GetAddress("glCullFace");
-
- DeleteBuffersAddress = context.GetAddress("glDeleteBuffers");
- DeleteBuffersARBAddress = context.GetAddress("glDeleteBuffersARB");
- DeleteListsAddress = context.GetAddress("glDeleteLists");
- DeleteTexturesAddress = context.GetAddress("glDeleteTextures");
- DepthFuncAddress = context.GetAddress("glDepthFunc");
- DepthMaskAddress = context.GetAddress("glDepthMask");
- DisableAddress = context.GetAddress("glDisable");
- DisableClientStateAddress = context.GetAddress("glDisableClientState");
- DrawArraysAddress = context.GetAddress("glDrawArrays");
- DrawElementsAddress = context.GetAddress("glDrawElements");
-
- EnableAddress = context.GetAddress("glEnable");
- EnableClientStateAddress = context.GetAddress("glEnableClientState");
- EndAddress = context.GetAddress("glEnd");
- EndListAddress = context.GetAddress("glEndList");
- FogfAddress = context.GetAddress("glFogf");
- FogfvAddress = context.GetAddress("glFogfv");
- FogiAddress = context.GetAddress("glFogi");
-
- GenBuffersAddress = context.GetAddress("glGenBuffers");
- GenBuffersARBAddress = context.GetAddress("glGenBuffersARB");
- GenListsAddress = context.GetAddress("glGenLists");
- GenTexturesAddress = context.GetAddress("glGenTextures");
- GetErrorAddress = context.GetAddress("glGetError");
- GetIntegervAddress = context.GetAddress("glGetIntegerv");
- GetStringAddress = context.GetAddress("glGetString");
- GetTexImageAddress = context.GetAddress("glGetTexImage");
-
- HintAddress = context.GetAddress("glHint");
- LoadIdentityAddress = context.GetAddress("glLoadIdentity");
- LoadMatrixfAddress = context.GetAddress("glLoadMatrixf");
- MatrixModeAddress = context.GetAddress("glMatrixMode");
- MultMatrixfAddress = context.GetAddress("glMultMatrixf");
- NewListAddress = context.GetAddress("glNewList");
- ReadPixelsAddress = context.GetAddress("glReadPixels");
-
- TexCoord2fAddress = context.GetAddress("glTexCoord2f");
- TexCoordPointerAddress = context.GetAddress("glTexCoordPointer");
- TexImage2DAddress = context.GetAddress("glTexImage2D");
- TexParameteriAddress = context.GetAddress("glTexParameteri");
- TexSubImage2DAddress = context.GetAddress("glTexSubImage2D");
- Vertex3fAddress = context.GetAddress("glVertex3f");
- VertexPointerAddress = context.GetAddress("glVertexPointer");
- ViewportAddress = context.GetAddress("glViewport");
- }
-
- public static void UseArbVboAddresses() {
- BindBufferAddress = BindBufferARBAddress;
- BufferDataAddress = BufferDataARBAddress;
- BufferSubDataAddress = BufferSubDataARBAddress;
- DeleteBuffersAddress = DeleteBuffersARBAddress;
- GenBuffersAddress = GenBuffersARBAddress;
- }
- }
}
#endif
diff --git a/ClassicalSharp/Network/Protocols/Classic.cs b/ClassicalSharp/Network/Protocols/Classic.cs
index e60f33f12..834ab1bfa 100644
--- a/ClassicalSharp/Network/Protocols/Classic.cs
+++ b/ClassicalSharp/Network/Protocols/Classic.cs
@@ -1,355 +1,350 @@
-// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
-using System;
-using ClassicalSharp.Gui;
-using ClassicalSharp.Gui.Screens;
-using ClassicalSharp.Entities;
-using OpenTK;
-#if __MonoCS__
-using Ionic.Zlib;
-#else
-using System.IO.Compression;
-#endif
-using BlockID = System.UInt16;
-
-namespace ClassicalSharp.Network.Protocols {
-
- /// Implements the packets for the original classic.
- public sealed class ClassicProtocol : IProtocol {
-
- public ClassicProtocol(Game game) : base(game) { }
- bool receivedFirstPosition;
- DateTime mapReceiveStart;
- DeflateStream gzipStream;
- GZipHeaderReader gzipHeader;
- int mapSizeIndex, mapIndex, mapVolume;
- byte[] mapSize = new byte[4], map;
- FixedBufferStream mapPartStream;
- Screen prevScreen;
- bool prevCursorVisible;
-
- public override void Reset() {
- if (mapPartStream == null) mapPartStream = new FixedBufferStream(net.reader.buffer);
- receivedFirstPosition = false;
-
- net.Set(Opcode.Handshake, HandleHandshake, 131);
- net.Set(Opcode.Ping, HandlePing, 1);
- net.Set(Opcode.LevelInit, HandleLevelInit, 1);
- net.Set(Opcode.LevelDataChunk, HandleLevelDataChunk, 1028);
- net.Set(Opcode.LevelFinalise, HandleLevelFinalise, 7);
- net.Set(Opcode.SetBlock, HandleSetBlock, 8);
-
- net.Set(Opcode.AddEntity, HandleAddEntity, 74);
- net.Set(Opcode.EntityTeleport, HandleEntityTeleport, 10);
- net.Set(Opcode.RelPosAndOrientationUpdate, HandleRelPosAndOrientationUpdate, 7);
- net.Set(Opcode.RelPosUpdate, HandleRelPositionUpdate, 5);
- net.Set(Opcode.OrientationUpdate, HandleOrientationUpdate, 4);
- net.Set(Opcode.RemoveEntity, HandleRemoveEntity, 2);
-
- net.Set(Opcode.Message, HandleMessage, 66);
- net.Set(Opcode.Kick, HandleKick, 65);
- net.Set(Opcode.SetPermission, HandleSetPermission, 2);
- }
-
- public override void Tick() {
- if (receivedFirstPosition) {
- LocalPlayer player = game.LocalPlayer;
- WritePosition(player.Position, player.HeadY, player.HeadX);
- }
- }
-
- #if !ONLY_8BIT
- DeflateStream gzipStream2;
- byte[] map2;
- int mapIndex2;
- #endif
-
- #region Read
-
- void HandleHandshake() {
- byte protocolVer = reader.ReadUInt8();
- net.ServerName = reader.ReadString();
- net.ServerMotd = reader.ReadString();
- game.Chat.SetLogName(net.ServerName);
-
- game.LocalPlayer.Hacks.SetUserType(reader.ReadUInt8(), !net.cpeData.blockPerms);
- game.LocalPlayer.Hacks.HacksFlags = net.ServerName + net.ServerMotd;
- game.LocalPlayer.Hacks.UpdateHacksState();
- }
-
- void HandlePing() { }
-
- void HandleLevelInit() {
- if (gzipStream == null) StartLoadingState();
-
- // Fast map puts volume in header, doesn't bother with gzip
- if (net.cpeData.fastMap) {
- mapVolume = reader.ReadInt32();
- gzipHeader.done = true;
- mapSizeIndex = 4;
- map = new byte[mapVolume];
- }
- }
-
- void StartLoadingState() {
- game.World.Reset();
- game.WorldEvents.RaiseOnNewMap();
-
- prevScreen = game.Gui.activeScreen;
- if (prevScreen is LoadingScreen)
- prevScreen = null;
- prevCursorVisible = game.CursorVisible;
-
- game.Gui.SetNewScreen(new LoadingScreen(game, net.ServerName, net.ServerMotd), false);
- net.wom.CheckMotd();
- receivedFirstPosition = false;
- gzipHeader = new GZipHeaderReader();
-
- // Workaround because built in mono stream assumes that the end of stream
- // has been reached the first time a read call returns 0. (MS.NET doesn't)
- #if __MonoCS__
- gzipStream = new DeflateStream(mapPartStream, true);
- #else
- gzipStream = new DeflateStream(mapPartStream, CompressionMode.Decompress);
- if (OpenTK.Configuration.RunningOnMono) {
- throw new InvalidOperationException("You must compile ClassicalSharp with __MonoCS__ defined " +
- "to run on Mono, due to a limitation in Mono.");
- }
- #endif
-
- #if !ONLY_8BIT
- #if __MonoCS__
- gzipStream2 = new DeflateStream(mapPartStream, true);
- #else
- gzipStream2 = new DeflateStream(mapPartStream, CompressionMode.Decompress);
- #endif
- #endif
-
- mapSizeIndex = 0;
- mapIndex = 0;
- #if !ONLY_8BIT
- mapIndex2 = 0;
- #endif
- mapReceiveStart = DateTime.UtcNow;
- }
-
- void HandleLevelDataChunk() {
- // Workaround for some servers that send LevelDataChunk before LevelInit
- // due to their async packet sending behaviour.
- if (gzipStream == null) StartLoadingState();
-
- int usedLength = reader.ReadUInt16();
- mapPartStream.pos = 0;
- mapPartStream.bufferPos = reader.index;
- mapPartStream.len = usedLength;
-
- reader.Skip(1024);
- byte value = reader.ReadUInt8(); // progress in original classic, but we ignore it
-
- if (gzipHeader.done || gzipHeader.ReadHeader(mapPartStream)) {
- if (mapSizeIndex < 4) {
- mapSizeIndex += gzipStream.Read(mapSize, mapSizeIndex, 4 - mapSizeIndex);
- }
-
- if (mapSizeIndex == 4) {
- if (map == null) {
- mapVolume = mapSize[0] << 24 | mapSize[1] << 16 | mapSize[2] << 8 | mapSize[3];
- map = new byte[mapVolume];
- }
-
- #if !ONLY_8BIT
- if (reader.ExtendedBlocks && value != 0) {
- // Only allocate map2 when needed
- if (map2 == null) map2 = new byte[mapVolume];
- mapIndex2 += gzipStream2.Read(map2, mapIndex2, map2.Length - mapIndex2);
- } else {
- mapIndex += gzipStream.Read(map, mapIndex, map.Length - mapIndex);
- }
- #else
- mapIndex += gzipStream.Read(map, mapIndex, map.Length - mapIndex);
- #endif
- }
- }
-
- float progress = map == null ? 0 : (float)mapIndex / map.Length;
- game.WorldEvents.RaiseLoading(progress);
- }
-
- void HandleLevelFinalise() {
- game.Gui.SetNewScreen(null);
- game.Gui.activeScreen = prevScreen;
- if (prevScreen != null && prevCursorVisible != game.CursorVisible) {
- game.CursorVisible = prevCursorVisible;
- }
- prevScreen = null;
-
- int mapWidth = reader.ReadUInt16();
- int mapHeight = reader.ReadUInt16();
- int mapLength = reader.ReadUInt16();
-
- double loadingMs = (DateTime.UtcNow - mapReceiveStart).TotalMilliseconds;
- Utils.LogDebug("map loading took: " + loadingMs);
-
- game.World.SetNewMap(map, mapWidth, mapHeight, mapLength);
- #if !ONLY_8BIT
- if (reader.ExtendedBlocks) {
- // defer allocation of scond map array if possible
- game.World.blocks2 = map2 == null ? map : map2;
- BlockInfo.SetMaxUsed(map2 == null ? 255 : 767);
- }
- #endif
- game.WorldEvents.RaiseOnNewMapLoaded();
- net.wom.CheckSendWomID();
-
- map = null;
- gzipStream.Dispose();
- gzipStream = null;
- #if !ONLY_8BIT
- map2 = null;
- gzipStream2.Dispose();
- gzipStream2 = null;
- #endif
- GC.Collect();
- }
-
- void HandleSetBlock() {
- int x = reader.ReadUInt16();
- int y = reader.ReadUInt16();
- int z = reader.ReadUInt16();
- BlockID block = reader.ReadBlock();
- if (game.World.IsValidPos(x, y, z)) {
- game.UpdateBlock(x, y, z, block);
- }
- }
-
- void HandleAddEntity() {
- byte id = reader.ReadUInt8();
- string name = reader.ReadString();
- string skin = name;
- CheckName(id, ref name, ref skin);
- AddEntity(id, name, skin, true);
-
- // Workaround for some servers that declare they support ExtPlayerList,
- // but doesn't send ExtAddPlayerName packets.
- AddTablistEntry(id, name, name, "Players", 0);
- classicTabList[id >> 3] |= (byte)(1 << (id & 0x7));
- }
-
- void HandleEntityTeleport() {
- byte id = reader.ReadUInt8();
- ReadAbsoluteLocation(id, true);
- }
-
- void HandleRelPosAndOrientationUpdate() {
- byte id = reader.ReadUInt8();
- Vector3 v;
- v.X = reader.ReadInt8() / 32f;
- v.Y = reader.ReadInt8() / 32f;
- v.Z = reader.ReadInt8() / 32f;
-
- float rotY = (float)Utils.PackedToDegrees(reader.ReadUInt8());
- float headX = (float)Utils.PackedToDegrees(reader.ReadUInt8());
- LocationUpdate update = LocationUpdate.MakePosAndOri(v, rotY, headX, true);
- UpdateLocation(id, update, true);
- }
-
- void HandleRelPositionUpdate() {
- byte id = reader.ReadUInt8();
- Vector3 v;
- v.X = reader.ReadInt8() / 32f;
- v.Y = reader.ReadInt8() / 32f;
- v.Z = reader.ReadInt8() / 32f;
-
- LocationUpdate update = LocationUpdate.MakePos(v, true);
- UpdateLocation(id, update, true);
- }
-
- void HandleOrientationUpdate() {
- byte id = reader.ReadUInt8();
- float rotY = (float)Utils.PackedToDegrees(reader.ReadUInt8());
- float headX = (float)Utils.PackedToDegrees(reader.ReadUInt8());
-
- LocationUpdate update = LocationUpdate.MakeOri(rotY, headX);
- UpdateLocation(id, update, true);
- }
-
- void HandleRemoveEntity() {
- byte id = reader.ReadUInt8();
- RemoveEntity(id);
- }
-
- void HandleMessage() {
- byte type = reader.ReadUInt8();
- // Original vanilla server uses player ids in message types, 255 for server messages.
- bool prepend = !net.cpeData.useMessageTypes && type == 0xFF;
-
- if (!net.cpeData.useMessageTypes) type = (byte)MessageType.Normal;
- string text = reader.ReadChatString(ref type);
- if (prepend) text = "&e" + text;
-
- if (!Utils.CaselessStarts(text, "^detail.user")) {
- game.Chat.Add(text, (MessageType)type);
- }
- }
-
- void HandleKick() {
- string reason = reader.ReadString();
- game.Disconnect("&eLost connection to the server", reason);
- }
-
- void HandleSetPermission() {
- game.LocalPlayer.Hacks.SetUserType(reader.ReadUInt8(), !net.cpeData.blockPerms);
- game.LocalPlayer.Hacks.UpdateHacksState();
- }
-
- internal void ReadAbsoluteLocation(byte id, bool interpolate) {
- Vector3 P = reader.ReadPosition(id);
- float rotY = (float)Utils.PackedToDegrees(reader.ReadUInt8());
- float headX = (float)Utils.PackedToDegrees(reader.ReadUInt8());
-
- if (id == EntityList.SelfID) receivedFirstPosition = true;
- LocationUpdate update = LocationUpdate.MakePosAndOri(P, rotY, headX, false);
- UpdateLocation(id, update, interpolate);
- }
- #endregion
-
- #region Write
-
- internal void WriteChat(string text, bool partial) {
- int payload = !net.SupportsPartialMessages ? EntityList.SelfID : (partial ? 1 : 0);
- writer.WriteUInt8((byte)Opcode.Message);
- writer.WriteUInt8((byte)payload);
- writer.WriteString(text);
- }
-
- internal void WritePosition(Vector3 pos, float rotY, float headX) {
- int payload = net.cpeData.sendHeldBlock ? game.Inventory.Selected : EntityList.SelfID;
- writer.WriteUInt8((byte)Opcode.EntityTeleport);
-
- writer.WriteBlock((BlockID)payload); // held block when using HeldBlock, otherwise just 255
- writer.WritePosition(pos);
- writer.WriteUInt8(Utils.DegreesToPacked(rotY));
- writer.WriteUInt8(Utils.DegreesToPacked(headX));
- }
-
- internal void WriteSetBlock(int x, int y, int z, bool place, BlockID block) {
- writer.WriteUInt8((byte)Opcode.SetBlockClient);
- writer.WriteInt16((short)x);
- writer.WriteInt16((short)y);
- writer.WriteInt16((short)z);
- writer.WriteUInt8(place ? (byte)1 : (byte)0);
- writer.WriteBlock(block);
- }
-
- internal void WriteLogin(string username, string verKey) {
- byte payload = game.UseCPE ? (byte)0x42 : (byte)0x00;
- writer.WriteUInt8((byte)Opcode.Handshake);
-
- writer.WriteUInt8(7); // protocol version
- writer.WriteString(username);
- writer.WriteString(verKey);
- writer.WriteUInt8(payload);
- }
-
- #endregion
- }
-}
+// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
+using System;
+using ClassicalSharp.Gui;
+using ClassicalSharp.Gui.Screens;
+using ClassicalSharp.Entities;
+using OpenTK;
+#if __MonoCS__
+using Ionic.Zlib;
+#else
+using System.IO.Compression;
+#endif
+using BlockID = System.UInt16;
+
+namespace ClassicalSharp.Network.Protocols {
+
+ /// Implements the packets for the original classic.
+ public sealed class ClassicProtocol : IProtocol {
+
+ public ClassicProtocol(Game game) : base(game) { }
+ bool receivedFirstPosition;
+ DateTime mapReceiveStart;
+ DeflateStream gzipStream;
+ GZipHeaderReader gzipHeader;
+ int mapSizeIndex, mapIndex, mapVolume;
+ byte[] mapSize = new byte[4], map;
+ FixedBufferStream mapPartStream;
+ Screen prevScreen;
+
+ public override void Reset() {
+ if (mapPartStream == null) mapPartStream = new FixedBufferStream(net.reader.buffer);
+ receivedFirstPosition = false;
+
+ net.Set(Opcode.Handshake, HandleHandshake, 131);
+ net.Set(Opcode.Ping, HandlePing, 1);
+ net.Set(Opcode.LevelInit, HandleLevelInit, 1);
+ net.Set(Opcode.LevelDataChunk, HandleLevelDataChunk, 1028);
+ net.Set(Opcode.LevelFinalise, HandleLevelFinalise, 7);
+ net.Set(Opcode.SetBlock, HandleSetBlock, 8);
+
+ net.Set(Opcode.AddEntity, HandleAddEntity, 74);
+ net.Set(Opcode.EntityTeleport, HandleEntityTeleport, 10);
+ net.Set(Opcode.RelPosAndOrientationUpdate, HandleRelPosAndOrientationUpdate, 7);
+ net.Set(Opcode.RelPosUpdate, HandleRelPositionUpdate, 5);
+ net.Set(Opcode.OrientationUpdate, HandleOrientationUpdate, 4);
+ net.Set(Opcode.RemoveEntity, HandleRemoveEntity, 2);
+
+ net.Set(Opcode.Message, HandleMessage, 66);
+ net.Set(Opcode.Kick, HandleKick, 65);
+ net.Set(Opcode.SetPermission, HandleSetPermission, 2);
+ }
+
+ public override void Tick() {
+ if (receivedFirstPosition) {
+ LocalPlayer player = game.LocalPlayer;
+ WritePosition(player.Position, player.HeadY, player.HeadX);
+ }
+ }
+
+ #if !ONLY_8BIT
+ DeflateStream gzipStream2;
+ byte[] map2;
+ int mapIndex2;
+ #endif
+
+ #region Read
+
+ void HandleHandshake() {
+ byte protocolVer = reader.ReadUInt8();
+ net.ServerName = reader.ReadString();
+ net.ServerMotd = reader.ReadString();
+ game.Chat.SetLogName(net.ServerName);
+
+ game.LocalPlayer.Hacks.SetUserType(reader.ReadUInt8(), !net.cpeData.blockPerms);
+ game.LocalPlayer.Hacks.HacksFlags = net.ServerName + net.ServerMotd;
+ game.LocalPlayer.Hacks.UpdateHacksState();
+ }
+
+ void HandlePing() { }
+
+ void HandleLevelInit() {
+ if (gzipStream == null) StartLoadingState();
+
+ // Fast map puts volume in header, doesn't bother with gzip
+ if (net.cpeData.fastMap) {
+ mapVolume = reader.ReadInt32();
+ gzipHeader.done = true;
+ mapSizeIndex = 4;
+ map = new byte[mapVolume];
+ }
+ }
+
+ void StartLoadingState() {
+ game.World.Reset();
+ game.WorldEvents.RaiseOnNewMap();
+
+ prevScreen = game.Gui.activeScreen;
+ if (prevScreen is LoadingScreen) prevScreen = null;
+
+ game.Gui.SetNewScreen(new LoadingScreen(game, net.ServerName, net.ServerMotd), false);
+ net.wom.CheckMotd();
+ receivedFirstPosition = false;
+ gzipHeader = new GZipHeaderReader();
+
+ // Workaround because built in mono stream assumes that the end of stream
+ // has been reached the first time a read call returns 0. (MS.NET doesn't)
+ #if __MonoCS__
+ gzipStream = new DeflateStream(mapPartStream, true);
+ #else
+ gzipStream = new DeflateStream(mapPartStream, CompressionMode.Decompress);
+ if (OpenTK.Configuration.RunningOnMono) {
+ throw new InvalidOperationException("You must compile ClassicalSharp with __MonoCS__ defined " +
+ "to run on Mono, due to a limitation in Mono.");
+ }
+ #endif
+
+ #if !ONLY_8BIT
+ #if __MonoCS__
+ gzipStream2 = new DeflateStream(mapPartStream, true);
+ #else
+ gzipStream2 = new DeflateStream(mapPartStream, CompressionMode.Decompress);
+ #endif
+ #endif
+
+ mapSizeIndex = 0;
+ mapIndex = 0;
+ #if !ONLY_8BIT
+ mapIndex2 = 0;
+ #endif
+ mapReceiveStart = DateTime.UtcNow;
+ }
+
+ void HandleLevelDataChunk() {
+ // Workaround for some servers that send LevelDataChunk before LevelInit
+ // due to their async packet sending behaviour.
+ if (gzipStream == null) StartLoadingState();
+
+ int usedLength = reader.ReadUInt16();
+ mapPartStream.pos = 0;
+ mapPartStream.bufferPos = reader.index;
+ mapPartStream.len = usedLength;
+
+ reader.Skip(1024);
+ byte value = reader.ReadUInt8(); // progress in original classic, but we ignore it
+
+ if (gzipHeader.done || gzipHeader.ReadHeader(mapPartStream)) {
+ if (mapSizeIndex < 4) {
+ mapSizeIndex += gzipStream.Read(mapSize, mapSizeIndex, 4 - mapSizeIndex);
+ }
+
+ if (mapSizeIndex == 4) {
+ if (map == null) {
+ mapVolume = mapSize[0] << 24 | mapSize[1] << 16 | mapSize[2] << 8 | mapSize[3];
+ map = new byte[mapVolume];
+ }
+
+ #if !ONLY_8BIT
+ if (reader.ExtendedBlocks && value != 0) {
+ // Only allocate map2 when needed
+ if (map2 == null) map2 = new byte[mapVolume];
+ mapIndex2 += gzipStream2.Read(map2, mapIndex2, map2.Length - mapIndex2);
+ } else {
+ mapIndex += gzipStream.Read(map, mapIndex, map.Length - mapIndex);
+ }
+ #else
+ mapIndex += gzipStream.Read(map, mapIndex, map.Length - mapIndex);
+ #endif
+ }
+ }
+
+ float progress = map == null ? 0 : (float)mapIndex / map.Length;
+ game.WorldEvents.RaiseLoading(progress);
+ }
+
+ void HandleLevelFinalise() {
+ game.Gui.SetNewScreen(null);
+ game.Gui.activeScreen = prevScreen;
+ game.Gui.CalcCursorVisible();
+ prevScreen = null;
+
+ int mapWidth = reader.ReadUInt16();
+ int mapHeight = reader.ReadUInt16();
+ int mapLength = reader.ReadUInt16();
+
+ double loadingMs = (DateTime.UtcNow - mapReceiveStart).TotalMilliseconds;
+ Utils.LogDebug("map loading took: " + loadingMs);
+
+ game.World.SetNewMap(map, mapWidth, mapHeight, mapLength);
+ #if !ONLY_8BIT
+ if (reader.ExtendedBlocks) {
+ // defer allocation of scond map array if possible
+ game.World.blocks2 = map2 == null ? map : map2;
+ BlockInfo.SetMaxUsed(map2 == null ? 255 : 767);
+ }
+ #endif
+ game.WorldEvents.RaiseOnNewMapLoaded();
+ net.wom.CheckSendWomID();
+
+ map = null;
+ gzipStream.Dispose();
+ gzipStream = null;
+ #if !ONLY_8BIT
+ map2 = null;
+ gzipStream2.Dispose();
+ gzipStream2 = null;
+ #endif
+ GC.Collect();
+ }
+
+ void HandleSetBlock() {
+ int x = reader.ReadUInt16();
+ int y = reader.ReadUInt16();
+ int z = reader.ReadUInt16();
+ BlockID block = reader.ReadBlock();
+ if (game.World.IsValidPos(x, y, z)) {
+ game.UpdateBlock(x, y, z, block);
+ }
+ }
+
+ void HandleAddEntity() {
+ byte id = reader.ReadUInt8();
+ string name = reader.ReadString();
+ string skin = name;
+ CheckName(id, ref name, ref skin);
+ AddEntity(id, name, skin, true);
+
+ // Workaround for some servers that declare they support ExtPlayerList,
+ // but doesn't send ExtAddPlayerName packets.
+ AddTablistEntry(id, name, name, "Players", 0);
+ classicTabList[id >> 3] |= (byte)(1 << (id & 0x7));
+ }
+
+ void HandleEntityTeleport() {
+ byte id = reader.ReadUInt8();
+ ReadAbsoluteLocation(id, true);
+ }
+
+ void HandleRelPosAndOrientationUpdate() {
+ byte id = reader.ReadUInt8();
+ Vector3 v;
+ v.X = reader.ReadInt8() / 32f;
+ v.Y = reader.ReadInt8() / 32f;
+ v.Z = reader.ReadInt8() / 32f;
+
+ float rotY = (float)Utils.PackedToDegrees(reader.ReadUInt8());
+ float headX = (float)Utils.PackedToDegrees(reader.ReadUInt8());
+ LocationUpdate update = LocationUpdate.MakePosAndOri(v, rotY, headX, true);
+ UpdateLocation(id, update, true);
+ }
+
+ void HandleRelPositionUpdate() {
+ byte id = reader.ReadUInt8();
+ Vector3 v;
+ v.X = reader.ReadInt8() / 32f;
+ v.Y = reader.ReadInt8() / 32f;
+ v.Z = reader.ReadInt8() / 32f;
+
+ LocationUpdate update = LocationUpdate.MakePos(v, true);
+ UpdateLocation(id, update, true);
+ }
+
+ void HandleOrientationUpdate() {
+ byte id = reader.ReadUInt8();
+ float rotY = (float)Utils.PackedToDegrees(reader.ReadUInt8());
+ float headX = (float)Utils.PackedToDegrees(reader.ReadUInt8());
+
+ LocationUpdate update = LocationUpdate.MakeOri(rotY, headX);
+ UpdateLocation(id, update, true);
+ }
+
+ void HandleRemoveEntity() {
+ byte id = reader.ReadUInt8();
+ RemoveEntity(id);
+ }
+
+ void HandleMessage() {
+ byte type = reader.ReadUInt8();
+ // Original vanilla server uses player ids in message types, 255 for server messages.
+ bool prepend = !net.cpeData.useMessageTypes && type == 0xFF;
+
+ if (!net.cpeData.useMessageTypes) type = (byte)MessageType.Normal;
+ string text = reader.ReadChatString(ref type);
+ if (prepend) text = "&e" + text;
+
+ if (!Utils.CaselessStarts(text, "^detail.user")) {
+ game.Chat.Add(text, (MessageType)type);
+ }
+ }
+
+ void HandleKick() {
+ string reason = reader.ReadString();
+ game.Disconnect("&eLost connection to the server", reason);
+ }
+
+ void HandleSetPermission() {
+ game.LocalPlayer.Hacks.SetUserType(reader.ReadUInt8(), !net.cpeData.blockPerms);
+ game.LocalPlayer.Hacks.UpdateHacksState();
+ }
+
+ internal void ReadAbsoluteLocation(byte id, bool interpolate) {
+ Vector3 P = reader.ReadPosition(id);
+ float rotY = (float)Utils.PackedToDegrees(reader.ReadUInt8());
+ float headX = (float)Utils.PackedToDegrees(reader.ReadUInt8());
+
+ if (id == EntityList.SelfID) receivedFirstPosition = true;
+ LocationUpdate update = LocationUpdate.MakePosAndOri(P, rotY, headX, false);
+ UpdateLocation(id, update, interpolate);
+ }
+ #endregion
+
+ #region Write
+
+ internal void WriteChat(string text, bool partial) {
+ int payload = !net.SupportsPartialMessages ? EntityList.SelfID : (partial ? 1 : 0);
+ writer.WriteUInt8((byte)Opcode.Message);
+ writer.WriteUInt8((byte)payload);
+ writer.WriteString(text);
+ }
+
+ internal void WritePosition(Vector3 pos, float rotY, float headX) {
+ int payload = net.cpeData.sendHeldBlock ? game.Inventory.Selected : EntityList.SelfID;
+ writer.WriteUInt8((byte)Opcode.EntityTeleport);
+
+ writer.WriteBlock((BlockID)payload); // held block when using HeldBlock, otherwise just 255
+ writer.WritePosition(pos);
+ writer.WriteUInt8(Utils.DegreesToPacked(rotY));
+ writer.WriteUInt8(Utils.DegreesToPacked(headX));
+ }
+
+ internal void WriteSetBlock(int x, int y, int z, bool place, BlockID block) {
+ writer.WriteUInt8((byte)Opcode.SetBlockClient);
+ writer.WriteInt16((short)x);
+ writer.WriteInt16((short)y);
+ writer.WriteInt16((short)z);
+ writer.WriteUInt8(place ? (byte)1 : (byte)0);
+ writer.WriteBlock(block);
+ }
+
+ internal void WriteLogin(string username, string verKey) {
+ byte payload = game.UseCPE ? (byte)0x42 : (byte)0x00;
+ writer.WriteUInt8((byte)Opcode.Handshake);
+
+ writer.WriteUInt8(7); // protocol version
+ writer.WriteString(username);
+ writer.WriteString(verKey);
+ writer.WriteUInt8(payload);
+ }
+
+ #endregion
+ }
+}
diff --git a/ClassicalSharp/Utils/Camera.cs b/ClassicalSharp/Utils/Camera.cs
index dea1a3a54..22396c58b 100644
--- a/ClassicalSharp/Utils/Camera.cs
+++ b/ClassicalSharp/Utils/Camera.cs
@@ -67,9 +67,9 @@ namespace ClassicalSharp {
int cenX = topLeft.X + game.Width / 2;
int cenY = topLeft.Y + game.Height / 2;
- game.DesktopCursorPos = new Point(cenX, cenY);
+ game.window.DesktopCursorPos = new Point(cenX, cenY);
// Fixes issues with large DPI displays on Windows >= 8.0.
- previous = game.DesktopCursorPos;
+ previous = game.window.DesktopCursorPos;
}
public override void RegrabMouse() {
@@ -127,8 +127,8 @@ namespace ClassicalSharp {
public override void UpdateMouse() {
if (game.Gui.ActiveScreen.HandlesAllInput) {
delta = Point.Empty;
- } else if (game.Focused) {
- Point pos = game.DesktopCursorPos;
+ } else if (game.window.Focused) {
+ Point pos = game.window.DesktopCursorPos;
delta = new Point(pos.X - previous.X, pos.Y - previous.Y);
CentreMousePosition();
}
diff --git a/src/Client/Game.c b/src/Client/Game.c
index c980dc677..76aa0be45 100644
--- a/src/Client/Game.c
+++ b/src/Client/Game.c
@@ -120,21 +120,6 @@ void Game_SetDefaultTexturePack(STRING_PURE String* texPack) {
Options_Set(OPT_DEFAULT_TEX_PACK, texPack);
}
-
-bool game_CursorVisible = true, game_realCursorVisible = true;
-bool Game_GetCursorVisible(void) { return game_CursorVisible; }
-bool Game_GetRealCursorVisible(void) { return game_realCursorVisible; }
-void Game_SetCursorVisible(bool visible) {
- /* Defer mouse visibility changes */
- game_realCursorVisible = visible;
- if (Gui_OverlaysCount > 0) return;
-
- /* Only set the value when it has changed */
- if (game_CursorVisible == visible) return;
- Window_SetCursorVisible(visible);
- game_CursorVisible = visible;
-}
-
bool Game_ChangeTerrainAtlas(struct Bitmap* atlas) {
String terrain = String_FromConst("terrain.png");
if (!Game_ValidateBitmap(&terrain, atlas)) return false;
diff --git a/src/Client/Game.h b/src/Client/Game.h
index 05fd74337..ba4cbd671 100644
--- a/src/Client/Game.h
+++ b/src/Client/Game.h
@@ -76,9 +76,6 @@ Real32 Game_GetChatScale(void);
void Game_GetDefaultTexturePack(STRING_TRANSIENT String* texPack);
void Game_SetDefaultTexturePack(STRING_PURE String* texPack);
-bool Game_GetCursorVisible(void);
-bool Game_GetRealCursorVisible(void);
-void Game_SetCursorVisible(bool visible);
bool Game_ChangeTerrainAtlas(struct Bitmap* atlas);
void Game_SetViewDistance(Int32 distance, bool userDist);
diff --git a/src/Client/Gui.c b/src/Client/Gui.c
index fc1c59eb1..3cd70c054 100644
--- a/src/Client/Gui.c
+++ b/src/Client/Gui.c
@@ -42,7 +42,7 @@ void GuiElement_Reset(struct GuiElem* elem) {
void Screen_Reset(struct Screen* screen) {
GuiElement_Reset((struct GuiElem*)screen);
- screen->HandlesAllInput = false;
+ screen->HandlesAllInput = true;
screen->BlocksWorld = false;
screen->HidesHUD = false;
screen->RenderHUDOver = false;
@@ -147,16 +147,10 @@ void Gui_FreeActive(void) {
void Gui_SetActive(struct Screen* screen) {
InputHandler_ScreenChanged(Gui_Active, screen);
-
- if (!screen) {
- Game_SetCursorVisible(false);
- if (Window_Focused) { Camera_Active->RegrabMouse(); }
- } else if (!Gui_Active) {
- Game_SetCursorVisible(true);
- }
-
if (screen) { Elem_Init(screen); }
+
Gui_Active = screen;
+ Gui_CalcCursorVisible();
}
void Gui_RefreshHud(void) { Elem_Recreate(Gui_HUD); }
@@ -164,8 +158,6 @@ void Gui_ShowOverlay(struct Screen* overlay, bool atFront) {
if (Gui_OverlaysCount == GUI_MAX_OVERLAYS) {
ErrorHandler_Fail("Cannot have more than 6 overlays");
}
- bool visible = Game_GetCursorVisible();
- if (!Gui_OverlaysCount) Game_SetCursorVisible(true);
if (atFront) {
Int32 i;
@@ -179,8 +171,8 @@ void Gui_ShowOverlay(struct Screen* overlay, bool atFront) {
}
Gui_OverlaysCount++;
- if (Gui_OverlaysCount == 1) Game_SetCursorVisible(visible); /* Save cursor visibility state */
Elem_Init(overlay);
+ Gui_CalcCursorVisible();
}
Int32 Gui_IndexOverlay(struct Screen* overlay) {
@@ -202,9 +194,7 @@ void Gui_FreeOverlay(struct Screen* overlay) {
Gui_OverlaysCount--;
Gui_Overlays[Gui_OverlaysCount] = NULL;
-
- if (!Gui_OverlaysCount) { Game_SetCursorVisible(Game_GetRealCursorVisible()); }
- Camera_Active->RegrabMouse();
+ Gui_CalcCursorVisible();
}
void Gui_RenderGui(Real64 delta) {
@@ -233,6 +223,17 @@ void Gui_OnResize(void) {
}
}
+bool gui_cursorVisible = true;
+void Gui_CalcCursorVisible(void) {
+ bool vis = Gui_GetActiveScreen()->HandlesAllInput;
+ if (vis == gui_cursorVisible) return;
+ gui_cursorVisible = vis;
+
+ Window_SetCursorVisible(vis);
+ if (Window_Focused)
+ Camera_Active->RegrabMouse();
+}
+
void TextAtlas_Make(struct TextAtlas* atlas, STRING_PURE String* chars, struct FontDesc* font, STRING_PURE String* prefix) {
struct DrawTextArgs args; DrawTextArgs_Make(&args, prefix, font, true);
diff --git a/src/Client/Gui.h b/src/Client/Gui.h
index 704481b3e..d3a497a4a 100644
--- a/src/Client/Gui.h
+++ b/src/Client/Gui.h
@@ -87,7 +87,7 @@ Int32 Gui_IndexOverlay(struct Screen* overlay);
void Gui_FreeOverlay(struct Screen* overlay);
void Gui_RenderGui(Real64 delta);
void Gui_OnResize(void);
-
+void Gui_CalcCursorVisible(void);
#define TEXTATLAS_MAX_WIDTHS 16
struct TextAtlas {
diff --git a/src/Client/Menus.c b/src/Client/Menus.c
index 176338745..7d28c07e6 100644
--- a/src/Client/Menus.c
+++ b/src/Client/Menus.c
@@ -523,7 +523,6 @@ struct ListScreen* ListScreen_MakeInstance(void) {
screen->VTABLE->Init = ListScreen_Init;
screen->VTABLE->Render = ListScreen_Render;
screen->VTABLE->Free = ListScreen_Free;
- screen->HandlesAllInput = true;
return screen;
}
@@ -622,7 +621,6 @@ static void MenuScreen_MakeInstance(struct MenuScreen* screen, struct Widget** w
screen->VTABLE->Render = MenuScreen_Render;
screen->VTABLE->Free = MenuScreen_Free;
- screen->HandlesAllInput = true;
screen->Widgets = widgets;
screen->WidgetsCount = count;
screen->ContextLost = MenuScreen_ContextLost;
diff --git a/src/Client/PacketHandlers.c b/src/Client/PacketHandlers.c
index 7d0fbaa3d..e410a672c 100644
--- a/src/Client/PacketHandlers.c
+++ b/src/Client/PacketHandlers.c
@@ -312,7 +312,7 @@ UInt8 mapSize[4];
UInt8* map;
struct Stream mapPartStream;
struct Screen* prevScreen;
-bool prevCursorVisible, receivedFirstPosition;
+bool receivedFirstPosition;
void Classic_WriteChat(struct Stream* stream, STRING_PURE String* text, bool partial) {
Int32 payload = !ServerConnection_SupportsPartialMessages ? ENTITIES_SELF_ID : (partial ? 1 : 0);
@@ -385,7 +385,6 @@ static void Classic_StartLoading(struct Stream* stream) {
Gui_FreeActive();
prevScreen = NULL;
}
- prevCursorVisible = Game_GetCursorVisible();
Gui_SetActive(LoadingScreen_MakeInstance(&ServerConnection_ServerName, &ServerConnection_ServerMOTD));
WoM_CheckMotd();
@@ -458,10 +457,8 @@ static void Classic_LevelDataChunk(struct Stream* stream) {
static void Classic_LevelFinalise(struct Stream* stream) {
Gui_ReplaceActive(NULL);
Gui_Active = prevScreen;
- if (prevScreen && prevCursorVisible != Game_GetCursorVisible()) {
- Game_SetCursorVisible(prevCursorVisible);
- }
prevScreen = NULL;
+ Gui_CalcCursorVisible();
Int32 mapWidth = Stream_ReadU16_BE(stream);
Int32 mapHeight = Stream_ReadU16_BE(stream);
diff --git a/src/Client/Screens.c b/src/Client/Screens.c
index ed04d5200..d15440da7 100644
--- a/src/Client/Screens.c
+++ b/src/Client/Screens.c
@@ -25,7 +25,7 @@ struct InventoryScreen {
Screen_Layout
struct FontDesc Font;
struct TableWidget Table;
- bool ReleasedInv;
+ bool ReleasedInv, DeferredSelect;
};
struct StatusScreen {
@@ -126,6 +126,18 @@ static void InventoryScreen_ContextRecreated(void* obj) {
Elem_Recreate(&screen->Table);
}
+static void InventoryScreen_MoveToSelected(struct InventoryScreen* screen) {
+ struct TableWidget* table = &screen->Table;
+ TableWidget_SetBlockTo(table, Inventory_SelectedBlock);
+ Elem_Recreate(table);
+ screen->DeferredSelect = false;
+
+ /* User is holding invalid block */
+ if (table->SelectedIndex == -1) {
+ TableWidget_MakeDescTex(table, Inventory_SelectedBlock);
+ }
+}
+
static void InventoryScreen_Init(struct GuiElem* elem) {
struct InventoryScreen* screen = (struct InventoryScreen*)elem;
Font_Make(&screen->Font, &Game_FontName, 16, FONT_STYLE_NORMAL);
@@ -135,10 +147,10 @@ static void InventoryScreen_Init(struct GuiElem* elem) {
screen->Table.ElementsPerRow = Game_PureClassic ? 9 : 10;
Elem_Init(&screen->Table);
- /* User is holding invalid block */
- if (screen->Table.SelectedIndex == -1) {
- TableWidget_MakeDescTex(&screen->Table, Inventory_SelectedBlock);
- }
+ /* Can't immediately move to selected here, because cursor visibility
+ might be toggled after Init() is called. This causes the cursor to
+ be moved back to the middle of the window. */
+ screen->DeferredSelect = true;
Key_KeyRepeat = true;
Event_RegisterVoid(&BlockEvents_PermissionsChanged, screen, InventoryScreen_OnBlockChanged);
@@ -149,6 +161,7 @@ static void InventoryScreen_Init(struct GuiElem* elem) {
static void InventoryScreen_Render(struct GuiElem* elem, Real64 delta) {
struct InventoryScreen* screen = (struct InventoryScreen*)elem;
+ if (screen->DeferredSelect) InventoryScreen_MoveToSelected(screen);
Elem_Render(&screen->Table, delta);
}
@@ -238,7 +251,6 @@ struct Screen* InventoryScreen_MakeInstance(void) {
Mem_Set(screen, 0, sizeof(struct InventoryScreen));
screen->VTABLE = &InventoryScreen_VTABLE;
Screen_Reset((struct Screen*)screen);
- screen->HandlesAllInput = true;
screen->VTABLE->HandlesKeyDown = InventoryScreen_HandlesKeyDown;
screen->VTABLE->HandlesKeyUp = InventoryScreen_HandlesKeyUp;
@@ -424,6 +436,7 @@ struct Screen* StatusScreen_MakeInstance(void) {
Mem_Set(screen, 0, sizeof(struct StatusScreen));
screen->VTABLE = &StatusScreen_VTABLE;
Screen_Reset((struct Screen*)screen);
+ screen->HandlesAllInput = false;
screen->OnResize = StatusScreen_OnResize;
screen->VTABLE->Init = StatusScreen_Init;
@@ -592,7 +605,6 @@ static void LoadingScreen_Make(struct LoadingScreen* screen, struct GuiElementVT
Mem_Set(screen, 0, sizeof(struct LoadingScreen));
screen->VTABLE = vtable;
Screen_Reset((struct Screen*)screen);
- screen->HandlesAllInput = true;
screen->VTABLE->HandlesKeyDown = LoadingScreen_HandlesKeyDown;
screen->VTABLE->HandlesKeyPress = LoadingScreen_HandlesKeyPress;
@@ -721,10 +733,10 @@ static void ChatScreen_UpdateAltTextY(struct ChatScreen* screen) {
static void ChatScreen_SetHandlesAllInput(struct ChatScreen* screen, bool handles) {
screen->HandlesAllInput = handles;
Gui_HUD->HandlesAllInput = handles;
+ Gui_CalcCursorVisible();
}
static void ChatScreen_OpenInput(struct ChatScreen* screen, STRING_PURE String* initialText) {
- Game_SetCursorVisible(true);
screen->SuppressNextPress = true;
ChatScreen_SetHandlesAllInput(screen, true);
Key_KeyRepeat = true;
@@ -908,9 +920,6 @@ static bool ChatScreen_HandlesKeyDown(struct GuiElem* elem, Key key) {
if (screen->HandlesAllInput) { /* text input bar */
if (key == KeyBind_Get(KeyBind_SendChat) || key == Key_KeypadEnter || key == KeyBind_Get(KeyBind_PauseOrExit)) {
ChatScreen_SetHandlesAllInput(screen, false);
- /* when underlying screen is HUD, user is interacting with the world normally */
- Game_SetCursorVisible(Gui_GetUnderlyingScreen() != Gui_HUD);
- Camera_Active->RegrabMouse();
Key_KeyRepeat = false;
if (key == KeyBind_Get(KeyBind_PauseOrExit)) {
@@ -1064,7 +1073,7 @@ static void ChatScreen_ContextLost(void* obj) {
if (screen->HandlesAllInput) {
String_AppendString(&chatInInput, &screen->Input.Base.Text);
- Game_SetCursorVisible(false);
+ Gui_CalcCursorVisible();
}
Elem_TryFree(&screen->Chat);
@@ -1181,6 +1190,7 @@ struct Screen* ChatScreen_MakeInstance(void) {
Mem_Set(screen, 0, sizeof(struct ChatScreen));
screen->VTABLE = &ChatScreen_VTABLE;
Screen_Reset((struct Screen*)screen);
+ screen->HandlesAllInput = false;
screen->InputOldHeight = -1;
screen->LastDownloadStatus = Int32_MinValue;
@@ -1378,6 +1388,7 @@ struct Screen* HUDScreen_MakeInstance(void) {
Mem_Set(screen, 0, sizeof(struct HUDScreen));
screen->VTABLE = &HUDScreenVTABLE;
Screen_Reset((struct Screen*)screen);
+ screen->HandlesAllInput = false;
screen->OnResize = HUDScreen_OnResize;
screen->VTABLE->Init = HUDScreen_Init;
@@ -1577,7 +1588,6 @@ struct Screen* DisconnectScreen_MakeInstance(STRING_PURE String* title, STRING_P
Mem_Set(screen, 0, sizeof(struct DisconnectScreen));
screen->VTABLE = &DisconnectScreen_VTABLE;
Screen_Reset((struct Screen*)screen);
- screen->HandlesAllInput = true;
String titleScreen = String_InitAndClearArray(screen->TitleBuffer);
String_AppendString(&titleScreen, title);
diff --git a/src/Client/Widgets.c b/src/Client/Widgets.c
index 8fa52aff4..a407c8091 100644
--- a/src/Client/Widgets.c
+++ b/src/Client/Widgets.c
@@ -658,8 +658,6 @@ static void TableWidget_Init(struct GuiElem* elem) {
ScrollbarWidget_Create(&widget->Scroll);
TableWidget_RecreateElements(widget);
Widget_Reposition(widget);
- TableWidget_SetBlockTo(widget, Inventory_SelectedBlock);
- Elem_Recreate(widget);
}
static void TableWidget_Render(struct GuiElem* elem, Real64 delta) {