When run out of VRAM, attempt to repeatedly half view distance instead of immediately crashing

This commit is contained in:
UnknownShadow200 2018-09-15 20:47:06 +10:00
parent 9b69574d7c
commit 759bfebedc
25 changed files with 270 additions and 224 deletions

View file

@ -29,7 +29,7 @@ Some of the per-platform functionality you'll be required to implement is:
### Types
* Integers and real numbers are always of a fixed size, see ```Typedefs.h```
* There are a few typedefs of integer types to provide better context in some functions
* structs are rarely typedef-ed
* A few common simple structs are typedef-ed, but are rarely otherwise.
* ```bool``` is an alias for 8 bit unsigned integer
* ```GfxResourceID``` is not constant type - can be pointer or integer, depending on underlying 3D graphics API
* ```PackedCol``` field order differs depending on the underlying 3D graphics API

View file

@ -62,7 +62,7 @@ namespace ClassicalSharp.Gui.Screens {
static void SetViewDist(Game g, string v) {
ViewDist raw = (ViewDist)Enum.Parse(typeof(ViewDist), v);
int dist = raw == ViewDist.FAR ? 512 : (raw == ViewDist.NORMAL ? 128 : (raw == ViewDist.SHORT ? 32 : 8));
g.SetViewDistance(dist, true);
g.UserSetViewDistance(dist);
}
static string GetPhysics(Game g) { return GetBool(((SinglePlayerServer)g.Server).physics.Enabled); }

View file

@ -45,7 +45,7 @@ namespace ClassicalSharp.Gui.Screens {
}
static string GetViewDist(Game g) { return g.ViewDistance.ToString(); }
static void SetViewDist(Game g, string v) { g.SetViewDistance(Int32.Parse(v), true); }
static void SetViewDist(Game g, string v) { g.UserSetViewDistance(Int32.Parse(v)); }
static string GetSmooth(Game g) { return GetBool(g.SmoothLighting); }
static void SetSmooth(Game g, string v) {

View file

@ -34,6 +34,10 @@ namespace ClassicalSharp {
public static event EmptyEventFunc ViewDistanceChanged;
public static void RaiseViewDistanceChanged() { Raise(ViewDistanceChanged); }
/// <summary> Raised when insufficient VRAM detected, need to free some GPU resources. </summary>
public static event EmptyEventFunc LowVRAMDetected;
public static void RaiseLowVRAMDetected() { Raise(LowVRAMDetected); }
/// <summary> Raised when the projection matrix changes. </summary>
public static event EmptyEventFunc ProjectionChanged;
public static void RaiseProjectionChanged() { Raise(ProjectionChanged); }

View file

@ -61,9 +61,10 @@ namespace ClassicalSharp {
LoadGuiOptions();
Chat = new Chat(); Components.Add(Chat);
Events.OnNewMap += OnNewMapCore;
Events.OnNewMapLoaded += OnNewMapLoadedCore;
Events.TextureChanged += TextureChangedCore;
Events.OnNewMap += OnNewMapCore;
Events.OnNewMapLoaded += OnNewMapLoadedCore;
Events.TextureChanged += TextureChangedCore;
Events.LowVRAMDetected += OnLowVRAMDetected;
BlockInfo.Allocate(256);
BlockInfo.Init();

View file

@ -90,12 +90,7 @@ namespace ClassicalSharp {
window.Close();
}
public void SetViewDistance(int distance, bool userDist) {
if (userDist) {
UserViewDistance = distance;
Options.Set(OptionsKey.ViewDist, distance);
}
public void SetViewDistance(int distance) {
distance = Math.Min(distance, MaxViewDistance);
if (distance == ViewDistance) return;
ViewDistance = distance;
@ -104,6 +99,12 @@ namespace ClassicalSharp {
UpdateProjection();
}
public void UserSetViewDistance(int distance) {
UserViewDistance = distance;
Options.Set(OptionsKey.ViewDist, distance);
SetViewDistance(distance);
}
public ScheduledTask AddScheduledTask(double interval, ScheduledTaskCallback callback) {
ScheduledTask task = new ScheduledTask();
task.Interval = interval; task.Callback = callback;
@ -268,13 +269,23 @@ namespace ClassicalSharp {
Events.RaiseChatFontChanged();
}
}
void OnLowVRAMDetected() {
if (UserViewDistance <= 16) throw new OutOfMemoryException("Out of video memory!");
UserViewDistance /= 2;
UserViewDistance = Math.Max(16, UserViewDistance);
ChunkUpdater.Refresh();
SetViewDistance(UserViewDistance);
Chat.Add("&cOut of VRAM! Halving view distance..");
}
Stopwatch frameTimer = new Stopwatch();
internal float limitMillis;
public void SetFpsLimit(FpsLimitMethod method) {
FpsLimit = method;
limitMillis = CalcLimitMillis(method);
Graphics.SetVSync(this, method == FpsLimitMethod.LimitVSync);
Graphics.SetVSync(this, method == FpsLimitMethod.LimitVSync);
}
internal float CalcLimitMillis(FpsLimitMethod method) {
@ -419,9 +430,11 @@ namespace ClassicalSharp {
Atlas1D.Dispose();
ModelCache.Dispose();
Entities.Dispose();
Events.OnNewMap -= OnNewMapCore;
Events.OnNewMapLoaded -= OnNewMapLoadedCore;
Events.TextureChanged -= TextureChangedCore;
Events.OnNewMap -= OnNewMapCore;
Events.OnNewMapLoaded -= OnNewMapLoadedCore;
Events.TextureChanged -= TextureChangedCore;
Events.LowVRAMDetected -= OnLowVRAMDetected;
for (int i = 0; i < Components.Count; i++)
Components[i].Dispose();

View file

@ -274,20 +274,20 @@ namespace ClassicalSharp {
for (int i = 0; i < viewDists.Length; i++) {
int dist = viewDists[i];
if (dist > game.UserViewDistance) {
game.SetViewDistance(dist, true); return;
game.UserSetViewDistance(dist); return;
}
}
game.SetViewDistance(viewDists[0], true);
game.UserSetViewDistance(viewDists[0]);
}
void CycleDistanceBackwards(int[] viewDists) {
for (int i = viewDists.Length - 1; i >= 0; i--) {
int dist = viewDists[i];
if (dist < game.UserViewDistance) {
game.SetViewDistance(dist, true); return;
game.UserSetViewDistance(dist); return;
}
}
game.SetViewDistance(viewDists[viewDists.Length - 1], true);
game.UserSetViewDistance(viewDists[viewDists.Length - 1]);
}
float fovIndex = -1;

View file

@ -24,18 +24,18 @@ using OpenTK;
namespace SharpDX.Direct3D9 {
public enum Direct3DError : uint {
public enum Direct3DError {
Ok = 0,
NotFound = 2150 | 0x88760000u,
MoreData = 2151 | 0x88760000u,
DeviceLost = 2152 | 0x88760000u,
DeviceNotReset = 2153 | 0x88760000u,
NotAvailable = 2154 | 0x88760000u,
OutOfVideoMemory = 380 | 0x88760000u,
InvalidDevice = 2155 | 0x88760000u,
InvalidCall = 2156 | 0x88760000u,
DriverInvalidCall = 2157 | 0x88760000u,
WasStillDrawing = 540 | 0x88760000u,
NotFound = 2150 | unchecked((int)0x88760000),
MoreData = 2151 | unchecked((int)0x88760000),
DeviceLost = 2152 | unchecked((int)0x88760000),
DeviceNotReset = 2153 | unchecked((int)0x88760000),
NotAvailable = 2154 | unchecked((int)0x88760000),
OutOfVideoMemory = 380 | unchecked((int)0x88760000),
InvalidDevice = 2155 | unchecked((int)0x88760000),
InvalidCall = 2156 | unchecked((int)0x88760000),
DriverInvalidCall = 2157 | unchecked((int)0x88760000),
WasStillDrawing = 540 | unchecked((int)0x88760000),
}
public class SharpDXException : Exception {
@ -66,20 +66,20 @@ namespace SharpDX.Direct3D9 {
public static bool CheckDeviceType(IntPtr ptr, int adapter, DeviceType devType,
Format adapterFormat, Format backBufferFormat, bool bWindowed) {
return Interop.Calli(ptr, adapter, (int)devType, (int)adapterFormat,
(int)backBufferFormat, bWindowed ? 1 : 0,(*(IntPtr**)ptr)[9]) == 0;
(int)backBufferFormat, bWindowed ? 1 : 0, (*(IntPtr**)ptr)[9]) == 0;
}
public static bool CheckDepthStencilMatch(IntPtr ptr, int adapter, DeviceType deviceType,
Format adapterFormat, Format renderTargetFormat, Format depthStencilFormat) {
return Interop.Calli(ptr, adapter, (int)deviceType, (int)adapterFormat,
(int)renderTargetFormat, (int)depthStencilFormat,(*(IntPtr**)ptr)[12]) == 0;
(int)renderTargetFormat, (int)depthStencilFormat, (*(IntPtr**)ptr)[12]) == 0;
}
public static IntPtr CreateDevice(IntPtr ptr, int adapter, DeviceType deviceType, IntPtr hFocusWindow,
CreateFlags behaviorFlags, PresentParameters presentParams) {
CreateFlags behaviorFlags, PresentParameters* presentParams) {
IntPtr devicePtr = IntPtr.Zero;
int res = Interop.Calli(ptr, adapter, (int)deviceType, hFocusWindow, (int)behaviorFlags, (IntPtr)(void*)&presentParams,
(IntPtr)(void*)&devicePtr,(*(IntPtr**)ptr)[16]);
int res = Interop.Calli(ptr, adapter, (int)deviceType, hFocusWindow, (int)behaviorFlags, (IntPtr)presentParams,
(IntPtr)(void*)&devicePtr, (*(IntPtr**)ptr)[16]);
if (res < 0) { throw new SharpDXException(res); }
return devicePtr;
@ -90,80 +90,67 @@ namespace SharpDX.Direct3D9 {
public unsafe static class Device {
public static int TestCooperativeLevel(IntPtr ptr) {
return Interop.Calli(ptr,(*(IntPtr**)ptr)[3]);
return Interop.Calli(ptr, (*(IntPtr**)ptr)[3]);
}
public static uint GetAvailableTextureMemory(IntPtr ptr) {
return (uint)Interop.Calli(ptr,(*(IntPtr**)ptr)[4]);
return (uint)Interop.Calli(ptr, (*(IntPtr**)ptr)[4]);
}
public static Capabilities GetCapabilities(IntPtr ptr) {
Capabilities caps = new Capabilities();
int res = Interop.Calli(ptr, (IntPtr)(void*)&caps,(*(IntPtr**)ptr)[7]);
public static void GetCapabilities(IntPtr ptr, Capabilities* caps) {
int res = Interop.Calli(ptr, (IntPtr)caps, (*(IntPtr**)ptr)[7]);
if (res < 0) { throw new SharpDXException(res); }
return caps;
}
public static int Reset(IntPtr ptr, PresentParameters presentParams) {
return Interop.Calli(ptr, (IntPtr)(void*)&presentParams,(*(IntPtr**)ptr)[16]);
public static int Reset(IntPtr ptr, PresentParameters* presentParams) {
return Interop.Calli(ptr, (IntPtr)presentParams, (*(IntPtr**)ptr)[16]);
}
public static int Present(IntPtr ptr) {
return Interop.Calli(ptr, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,(*(IntPtr**)ptr)[17]);
return Interop.Calli(ptr, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (*(IntPtr**)ptr)[17]);
}
public static IntPtr GetBackBuffer(IntPtr ptr, int iSwapChain, int iBackBuffer, BackBufferType type) {
IntPtr backBuffer = IntPtr.Zero;
int res = Interop.Calli(ptr, iSwapChain, iBackBuffer, (int)type, (IntPtr)(void*)&backBuffer,(*(IntPtr**)ptr)[18]);
public static void GetBackBuffer(IntPtr ptr, int iSwapChain, int iBackBuffer, BackBufferType type, IntPtr* backBuffer) {
int res = Interop.Calli(ptr, iSwapChain, iBackBuffer, (int)type, (IntPtr)backBuffer,(*(IntPtr**)ptr)[18]);
if (res < 0) { throw new SharpDXException(res); }
return backBuffer;
}
public static IntPtr CreateTexture(IntPtr ptr, int width, int height, int levels, Usage usage, Format format, Pool pool) {
IntPtr tex = IntPtr.Zero;
int res = Interop.Calli(ptr, width, height, levels, (int)usage, (int)format, (int)pool, (IntPtr)(void*)&tex, IntPtr.Zero,(*(IntPtr**)ptr)[23]);
public static void CreateTexture(IntPtr ptr, int width, int height, int levels, Usage usage, Format format, Pool pool, IntPtr* tex) {
int res = Interop.Calli(ptr, width, height, levels, (int)usage, (int)format, (int)pool, (IntPtr)tex, IntPtr.Zero, (*(IntPtr**)ptr)[23]);
if (res < 0) { throw new SharpDXException(res); }
return tex;
}
public static IntPtr CreateVertexBuffer(IntPtr ptr, int length, Usage usage, VertexFormat vertexFormat, Pool pool) {
IntPtr vb = IntPtr.Zero;
int res = Interop.Calli(ptr, length, (int)usage, (int)vertexFormat, (int)pool, (IntPtr)(void*)&vb, IntPtr.Zero,(*(IntPtr**)ptr)[26]);
if (res < 0) { throw new SharpDXException(res); }
return vb;
public static int CreateVertexBuffer(IntPtr ptr, int length, Usage usage, VertexFormat vertexFormat, Pool pool, IntPtr* vb) {
return Interop.Calli(ptr, length, (int)usage, (int)vertexFormat, (int)pool, (IntPtr)vb, IntPtr.Zero, (*(IntPtr**)ptr)[26]);
}
public static IntPtr CreateIndexBuffer(IntPtr ptr, int length, Usage usage, Format format, Pool pool) {
IntPtr ib = IntPtr.Zero;
int res = Interop.Calli(ptr, length, (int)usage, (int)format, (int)pool, (IntPtr)(void*)&ib, IntPtr.Zero,(*(IntPtr**)ptr)[27]);
public static void CreateIndexBuffer(IntPtr ptr, int length, Usage usage, Format format, Pool pool, IntPtr* ib) {
int res = Interop.Calli(ptr, length, (int)usage, (int)format, (int)pool, (IntPtr)ib, IntPtr.Zero, (*(IntPtr**)ptr)[27]);
if (res < 0) { throw new SharpDXException(res); }
return ib;
}
public static void UpdateTexture(IntPtr ptr, IntPtr srcTex, IntPtr dstTex) {
int res = Interop.Calli(ptr, srcTex, dstTex,(*(IntPtr**)ptr)[31]);
int res = Interop.Calli(ptr, srcTex, dstTex, (*(IntPtr**)ptr)[31]);
if (res < 0) { throw new SharpDXException(res); }
}
public static void GetRenderTargetData(IntPtr ptr, IntPtr renderTarget, IntPtr dstSurface) {
int res = Interop.Calli(ptr, renderTarget, dstSurface,(*(IntPtr**)ptr)[32]);
int res = Interop.Calli(ptr, renderTarget, dstSurface, (*(IntPtr**)ptr)[32]);
if (res < 0) { throw new SharpDXException(res); }
}
public static IntPtr CreateOffscreenPlainSurface(IntPtr ptr, int width, int height, Format format, Pool pool) {
IntPtr surface = IntPtr.Zero;
int res = Interop.Calli(ptr, width, height, (int)format, (int)pool, (IntPtr)(void*)&surface, IntPtr.Zero,(*(IntPtr**)ptr)[36]);
public static void CreateOffscreenPlainSurface(IntPtr ptr, int width, int height, Format format, Pool pool, IntPtr* surface) {
int res = Interop.Calli(ptr, width, height, (int)format, (int)pool, (IntPtr)surface, IntPtr.Zero, (*(IntPtr**)ptr)[36]);
if (res < 0) { throw new SharpDXException(res); }
return surface;
}
public static void BeginScene(IntPtr ptr) {
int res = Interop.Calli(ptr,(*(IntPtr**)ptr)[41]);
int res = Interop.Calli(ptr, (*(IntPtr**)ptr)[41]);
if (res < 0) { throw new SharpDXException(res); }
}
public static void EndScene(IntPtr ptr) {
int res = Interop.Calli(ptr,(*(IntPtr**)ptr)[42]);
int res = Interop.Calli(ptr, (*(IntPtr**)ptr)[42]);
if (res < 0) { throw new SharpDXException(res); }
}
@ -175,7 +162,7 @@ namespace SharpDX.Direct3D9 {
public static void SetTransform(IntPtr ptr, TransformState state, ref Matrix4 matrixRef) {
int res;
fixed (void* matrixRef_ = &matrixRef)
res = Interop.Calli(ptr, (int)state, (IntPtr)matrixRef_,(*(IntPtr**)ptr)[44]);
res = Interop.Calli(ptr, (int)state, (IntPtr)matrixRef_, (*(IntPtr**)ptr)[44]);
if (res < 0) { throw new SharpDXException(res); }
}
@ -188,17 +175,17 @@ namespace SharpDX.Direct3D9 {
}
public static void SetRenderState(IntPtr ptr, RenderState state, int value) {
int res = Interop.Calli(ptr, (int)state, value,(*(IntPtr**)ptr)[57]);
int res = Interop.Calli(ptr, (int)state, value, (*(IntPtr**)ptr)[57]);
if (res < 0) { throw new SharpDXException(res); }
}
public static void SetTexture(IntPtr ptr, int stage, IntPtr texture) {
int res = Interop.Calli(ptr, stage, texture,(*(IntPtr**)ptr)[65]);
int res = Interop.Calli(ptr, stage, texture, (*(IntPtr**)ptr)[65]);
if (res < 0) { throw new SharpDXException(res); }
}
public static void SetTextureStageState(IntPtr ptr, int stage, TextureStage type, int value) {
int res = Interop.Calli(ptr, stage, (int)type, value,(*(IntPtr**)ptr)[67]);
int res = Interop.Calli(ptr, stage, (int)type, value, (*(IntPtr**)ptr)[67]);
if (res < 0) { throw new SharpDXException(res); }
}
@ -213,7 +200,7 @@ namespace SharpDX.Direct3D9 {
}
public static void DrawIndexedPrimitives(IntPtr ptr, PrimitiveType type, int baseVertexIndex, int minVertexIndex, int numVertices, int startIndex, int primCount) {
int res = Interop.Calli(ptr, (int)type, baseVertexIndex, minVertexIndex, numVertices, startIndex, primCount,(*(IntPtr**)ptr)[82]);
int res = Interop.Calli(ptr, (int)type, baseVertexIndex, minVertexIndex, numVertices, startIndex, primCount, (*(IntPtr**)ptr)[82]);
if (res < 0) { throw new SharpDXException(res); }
}
@ -223,12 +210,12 @@ namespace SharpDX.Direct3D9 {
}
public static void SetStreamSource(IntPtr ptr, int streamNumber, IntPtr streamData, int offsetInBytes, int stride) {
int res = Interop.Calli(ptr, streamNumber, streamData, offsetInBytes, stride,(*(IntPtr**)ptr)[100]);
int res = Interop.Calli(ptr, streamNumber, streamData, offsetInBytes, stride, (*(IntPtr**)ptr)[100]);
if (res < 0) { throw new SharpDXException(res); }
}
public static void SetIndices(IntPtr ptr, IntPtr indexData) {
int res = Interop.Calli(ptr, indexData,(*(IntPtr**)ptr)[104]);
int res = Interop.Calli(ptr, indexData, (*(IntPtr**)ptr)[104]);
if (res < 0) { throw new SharpDXException(res); }
}
}
@ -537,7 +524,7 @@ namespace SharpDX.Direct3D9 {
public static LockedRectangle LockRectangle(IntPtr ptr, LockFlags flags) {
LockedRectangle rect = new LockedRectangle();
int res = Interop.Calli(ptr, (IntPtr)(void*)&rect, IntPtr.Zero, (int)flags,(*(IntPtr**)ptr)[13]);
int res = Interop.Calli(ptr, (IntPtr)(void*)&rect, IntPtr.Zero, (int)flags, (*(IntPtr**)ptr)[13]);
if (res < 0) { throw new SharpDXException(res); }
return rect;
}
@ -553,14 +540,14 @@ namespace SharpDX.Direct3D9 {
public static LockedRectangle LockRectangle(IntPtr ptr, int level, LockFlags flags) {
LockedRectangle rect = new LockedRectangle();
int res = Interop.Calli(ptr, level, (IntPtr)(void*)&rect, IntPtr.Zero, (int)flags,(*(IntPtr**)ptr)[19]);
int res = Interop.Calli(ptr, level, (IntPtr)(void*)&rect, IntPtr.Zero, (int)flags, (*(IntPtr**)ptr)[19]);
if (res < 0) { throw new SharpDXException(res); }
return rect;
}
public static LockedRectangle LockRectangle(IntPtr ptr, int level, D3DRect region, LockFlags flags) {
LockedRectangle rect = new LockedRectangle();
int res = Interop.Calli(ptr, level, (IntPtr)(void*)&rect, (IntPtr)(void*)&region, (int)flags,(*(IntPtr**)ptr)[19]);
int res = Interop.Calli(ptr, level, (IntPtr)(void*)&rect, (IntPtr)(void*)&region, (int)flags, (*(IntPtr**)ptr)[19]);
if (res < 0) { throw new SharpDXException(res); }
return rect;
}
@ -588,7 +575,7 @@ namespace SharpDX.Direct3D9 {
}
public static void UnlockRectangle(IntPtr ptr, int level) {
int res = Interop.Calli(ptr, level,(*(IntPtr**)ptr)[20]);
int res = Interop.Calli(ptr, level, (*(IntPtr**)ptr)[20]);
if (res < 0) { throw new SharpDXException(res); }
}
}

View file

@ -14,7 +14,7 @@ using D3D = SharpDX.Direct3D9;
namespace ClassicalSharp.GraphicsAPI {
/// <summary> Implements IGraphicsAPI using Direct3D 9. </summary>
public class Direct3D9Api : IGraphicsApi {
public unsafe class Direct3D9Api : IGraphicsApi {
IntPtr device, d3d;
const int texBufferSize = 512, iBufferSize = 4, vBufferSize = 2048;
@ -39,18 +39,19 @@ namespace ClassicalSharp.GraphicsAPI {
PresentParameters args = GetPresentArgs(640, 480);
try {
device = Direct3D.CreateDevice(d3d, adapter, DeviceType.Hardware, winHandle, createFlags, args);
device = Direct3D.CreateDevice(d3d, adapter, DeviceType.Hardware, winHandle, createFlags, &args);
} catch (SharpDXException) {
createFlags = CreateFlags.Mixed;
try {
device = Direct3D.CreateDevice(d3d, adapter, DeviceType.Hardware, winHandle, createFlags, args);
device = Direct3D.CreateDevice(d3d, adapter, DeviceType.Hardware, winHandle, createFlags, &args);
} catch (SharpDXException) {
createFlags = CreateFlags.Software;
device = Direct3D.CreateDevice(d3d, adapter, DeviceType.Hardware, winHandle, createFlags, args);
device = Direct3D.CreateDevice(d3d, adapter, DeviceType.Hardware, winHandle, createFlags, &args);
}
}
Capabilities caps = Device.GetCapabilities(device);
Capabilities caps;
Device.GetCapabilities(device, &caps);
MaxTexWidth = caps.MaxTextureWidth;
MaxTexHeight = caps.MaxTextureHeight;
@ -167,27 +168,26 @@ namespace ClassicalSharp.GraphicsAPI {
}
protected override int CreateTexture(int width, int height, IntPtr scan0, bool managedPool, bool mipmaps) {
IntPtr tex = IntPtr.Zero;
IntPtr tex = IntPtr.Zero, sys = IntPtr.Zero;
int levels = 1 + (mipmaps ? MipmapsLevels(width, height) : 0);
if (managedPool) {
tex = Device.CreateTexture(device, width, height, levels, Usage.None, Format.A8R8G8B8, Pool.Managed);
Device.CreateTexture(device, width, height, levels, Usage.None, Format.A8R8G8B8, Pool.Managed, &tex);
D3D.Texture.SetData(tex, 0, LockFlags.None, scan0, width * height * 4);
if (mipmaps) DoMipmaps(tex, 0, 0, width, height, scan0, false);
} else {
IntPtr sys = Device.CreateTexture(device, width, height, levels, Usage.None, Format.A8R8G8B8, Pool.SystemMemory);
Device.CreateTexture(device, width, height, levels, Usage.None, Format.A8R8G8B8, Pool.SystemMemory, &sys);
D3D.Texture.SetData(sys, 0, LockFlags.None, scan0, width * height * 4);
if (mipmaps) DoMipmaps(sys, 0, 0, width, height, scan0, false);
tex = Device.CreateTexture(device, width, height, levels, Usage.None, Format.A8R8G8B8, Pool.Default);
Device.CreateTexture(device, width, height, levels, Usage.None, Format.A8R8G8B8, Pool.Default, &tex);
Device.UpdateTexture(device, sys, tex);
Delete(ref sys);
}
return GetOrExpand(ref textures, tex, texBufferSize);
}
unsafe void DoMipmaps(IntPtr tex, int x, int y, int width,
int height, IntPtr scan0, bool partial) {
void DoMipmaps(IntPtr tex, int x, int y, int width, int height, IntPtr scan0, bool partial) {
IntPtr prev = scan0;
int lvls = MipmapsLevels(width, height);
@ -280,8 +280,11 @@ namespace ClassicalSharp.GraphicsAPI {
public override int CreateDynamicVb(VertexFormat format, int maxVertices) {
int size = maxVertices * strideSizes[(int)format];
IntPtr buffer = Device.CreateVertexBuffer(device, size, Usage.Dynamic | Usage.WriteOnly,
formatMapping[(int)format], Pool.Default);
IntPtr buffer = IntPtr.Zero;
int res = Device.CreateVertexBuffer(device, size, Usage.Dynamic | Usage.WriteOnly,
formatMapping[(int)format], Pool.Default, &buffer);
if (res < 0) throw new SharpDXException(res);
return GetOrExpand(ref vBuffers, buffer, iBufferSize);
}
@ -296,16 +299,27 @@ namespace ClassicalSharp.GraphicsAPI {
public override int CreateVb(IntPtr vertices, VertexFormat format, int count) {
int size = count * strideSizes[(int)format];
IntPtr buffer = Device.CreateVertexBuffer(device, size, Usage.WriteOnly,
formatMapping[(int)format], Pool.Default);
IntPtr buffer = IntPtr.Zero;
for (;;) {
int res = Device.CreateVertexBuffer(device, size, Usage.WriteOnly,
formatMapping[(int)format], Pool.Default, &buffer);
if (res >= 0) break;
if (res != (int)Direct3DError.OutOfVideoMemory) throw new SharpDXException(res);
Events.RaiseLowVRAMDetected();
}
DataBuffser.SetData(buffer, vertices, size, LockFlags.None);
return GetOrExpand(ref vBuffers, buffer, vBufferSize);
}
public override int CreateIb(IntPtr indices, int indicesCount) {
int size = indicesCount * sizeof(ushort);
IntPtr buffer = Device.CreateIndexBuffer(device, size, Usage.WriteOnly,
Format.Index16, Pool.Default);
IntPtr buffer = IntPtr.Zero;
Device.CreateIndexBuffer(device, size, Usage.WriteOnly,
Format.Index16, Pool.Default, &buffer);
DataBuffser.SetData(buffer, indices, size, LockFlags.None);
return GetOrExpand(ref iBuffers, buffer, iBufferSize);
}
@ -369,7 +383,7 @@ namespace ClassicalSharp.GraphicsAPI {
}
}
public unsafe override void LoadMatrix(ref Matrix4 matrix) {
public override void LoadMatrix(ref Matrix4 matrix) {
if (curMatrix == TransformState.Texture0) {
matrix.Row2.X = matrix.Row3.X; // NOTE: this hack fixes the texture movements.
Device.SetTextureStageState(device, 0, TextureStage.TextureTransformFlags, (int)TextureTransform.Count2);
@ -403,11 +417,11 @@ namespace ClassicalSharp.GraphicsAPI {
public override void EndFrame(Game game) {
Device.EndScene(device);
int code = Device.Present(device);
if (code >= 0) return;
int res = Device.Present(device);
if (res >= 0) return;
if ((uint)code != (uint)Direct3DError.DeviceLost)
throw new SharpDXException(code);
if (res != (int)Direct3DError.DeviceLost)
throw new SharpDXException(res);
// TODO: Make sure this actually works on all graphics cards.
@ -423,8 +437,8 @@ namespace ClassicalSharp.GraphicsAPI {
while (true) {
Thread.Sleep(16);
uint code = (uint)Device.TestCooperativeLevel(device);
if ((uint)code == (uint)Direct3DError.DeviceNotReset) return;
int res = Device.TestCooperativeLevel(device);
if (res == (int)Direct3DError.DeviceNotReset) return;
task.Callback(task);
}
@ -448,7 +462,7 @@ namespace ClassicalSharp.GraphicsAPI {
void RecreateDevice(Game game) {
PresentParameters args = GetPresentArgs(game.Width, game.Height);
while ((uint)Device.Reset(device, args) == (uint)Direct3DError.DeviceLost)
while (Device.Reset(device, &args) == (int)Direct3DError.DeviceLost)
LoopUntilRetrieved();
SetDefaultRenderStates();
@ -543,7 +557,7 @@ namespace ClassicalSharp.GraphicsAPI {
float totalMem;
internal override void MakeApiInfo() {
AdapterDetails details = Direct3D.GetAdapterIdentifier(d3d, 0);
AdapterDetails details = Direct3D.GetAdapterIdentifier(d3d, 0);
string adapter = details.Description;
totalMem = VideoMemoryMB;
@ -565,8 +579,9 @@ namespace ClassicalSharp.GraphicsAPI {
}
public override void TakeScreenshot(Stream output, int width, int height) {
IntPtr backbuffer = Device.GetBackBuffer(device, 0, 0, BackBufferType.Mono);
IntPtr temp = Device.CreateOffscreenPlainSurface(device, width, height, Format.X8R8G8B8, Pool.SystemMemory);
IntPtr backbuffer = IntPtr.Zero, temp = IntPtr.Zero;
Device.GetBackBuffer(device, 0, 0, BackBufferType.Mono, &backbuffer);
Device.CreateOffscreenPlainSurface(device, width, height, Format.X8R8G8B8, Pool.SystemMemory, &temp);
// For DX 8 use IDirect3DDevice8::CreateImageSurface
Device.GetRenderTargetData(device, backbuffer, temp);

View file

@ -539,9 +539,9 @@ namespace ClassicalSharp.GraphicsAPI {
bool isIntelRenderer, nvMem;
internal override void MakeApiInfo() {
string vendor = new String((sbyte*)GL.GetString(StringName.Vendor));
string vendor = new String((sbyte*)GL.GetString(StringName.Vendor));
string renderer = new String((sbyte*)GL.GetString(StringName.Renderer));
string version = new String((sbyte*)GL.GetString(StringName.Version));
string version = new String((sbyte*)GL.GetString(StringName.Version));
string extensions = new String((sbyte*)GL.GetString(StringName.Extensions));
int depthBits = 0;

View file

@ -357,7 +357,7 @@ namespace ClassicalSharp {
part.vIndex[Side.Top] += 4;
}
PackedCol[] lerp = new PackedCol[5];
PackedCol[] lerp = new PackedCol[5];
PackedCol[] lerpX = new PackedCol[5];
PackedCol[] lerpZ = new PackedCol[5];
PackedCol[] lerpY = new PackedCol[5];

View file

@ -227,7 +227,7 @@ namespace ClassicalSharp.Network.Protocols {
game.World.Env.SetCloudsLevel(reader.ReadInt16());
short maxViewDist = reader.ReadInt16();
game.MaxViewDistance = maxViewDist <= 0 ? 32768 : maxViewDist;
game.SetViewDistance(game.UserViewDistance, false);
game.SetViewDistance(game.UserViewDistance);
}
void HandleEnvWeatherType() {
@ -351,7 +351,7 @@ namespace ClassicalSharp.Network.Protocols {
case 4:
Utils.Clamp(ref value, -0x7FFF, 0x7FFF);
game.MaxViewDistance = value <= 0 ? 32768 : value;
game.SetViewDistance(game.UserViewDistance, false); break;
game.SetViewDistance(game.UserViewDistance); break;
case 5:
env.SetCloudsSpeed(value / 256f); break;
case 6:

View file

@ -89,7 +89,7 @@ namespace ClassicalSharp.Renderers {
Events.ViewDistanceChanged += ResetAllEnv;
Events.ContextLost += ContextLost;
Events.ContextRecreated += ContextRecreated;
game.SetViewDistance(game.UserViewDistance, false);
game.SetViewDistance(game.UserViewDistance);
}
void IGameComponent.Ready(Game game) { }
@ -195,9 +195,9 @@ namespace ClassicalSharp.Renderers {
const double log005 = -2.99573227355399;
double dist = log005 / -fogDensity;
game.SetViewDistance((int)dist, false);
game.SetViewDistance((int)dist);
} else {
game.SetViewDistance(game.UserViewDistance, false);
game.SetViewDistance(game.UserViewDistance);
}
}

View file

@ -35,7 +35,7 @@ static void LavaAnimation_Tick(UInt32* ptr, Int32 size) {
for (x = 0; x < size; x++) {
/* Calculate the colour at this coordinate in the heatmap */
/* Lookup table for (Int32)(1.2f * Math_SinF([ANGLE] * 22.5f * MATH_DEG2RAD)); */
/* Lookup table for (int)(1.2 * sin([ANGLE] * 22.5 * MATH_DEG2RAD)); */
/* [ANGLE] is integer x/y, so repeats every 16 intervals */
static Int8 sin_adj_table[16] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0 };
Int32 xx = x + sin_adj_table[y & 0xF], yy = y + sin_adj_table[x & 0xF];
@ -196,7 +196,7 @@ static void Animations_ReadDescription(struct Stream* stream, STRING_PURE String
}
if (anims_count == Array_Elems(anims_list)) {
Chat_AddRaw("&cCannot show over 256 animations"); return;
Chat_AddRaw("&cCannot show over 512 animations"); return;
}
data.TexLoc = tileX + (tileY * ATLAS2D_TILES_PER_ROW);
@ -240,7 +240,7 @@ static void Animations_Apply(struct AnimationData* data) {
if (data->Tick >= 0) return;
data->State++;
data->State %= data->StatesCount;
data->Tick = data->TickDelay;
data->Tick = data->TickDelay;
TextureLoc texLoc = data->TexLoc;
if (texLoc == 30 && anims_useLavaAnim) return;

View file

@ -8,6 +8,7 @@
#include "Game.h"
#include "ExtMath.h"
#include "Bitmap.h"
#include "Event.h"
//#define D3D_DISABLE_9EX causes compile errors
#if CC_BUILD_WIN
@ -148,8 +149,10 @@ void Gfx_Init(void) {
}
ErrorHandler_CheckOrFail(res, "Creating Direct3D9 device");
D3DCAPS9 caps = { 0 };
IDirect3DDevice9_GetDeviceCaps(device, &caps);
D3DCAPS9 caps;
res = IDirect3DDevice9_GetDeviceCaps(device, &caps);
ErrorHandler_CheckOrFail(res, "Getting Direct3D9 capabilities");
Gfx_MaxTexWidth = caps.MaxTextureWidth;
Gfx_MaxTexHeight = caps.MaxTextureHeight;
@ -446,9 +449,15 @@ static void D3D9_SetVbData(IDirect3DVertexBuffer9* buffer, void* data, Int32 siz
GfxResourceID Gfx_CreateVb(void* vertices, Int32 vertexFormat, Int32 count) {
Int32 size = count * Gfx_strideSizes[vertexFormat];
IDirect3DVertexBuffer9* vbuffer;
ReturnCode hresult = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_WRITEONLY,
d3d9_formatMappings[vertexFormat], D3DPOOL_DEFAULT, &vbuffer, NULL);
ErrorHandler_CheckOrFail(hresult, "D3D9_CreateVb");
for (;;) {
ReturnCode hresult = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_WRITEONLY,
d3d9_formatMappings[vertexFormat], D3DPOOL_DEFAULT, &vbuffer, NULL);
if (!hresult) break;
if (hresult != D3DERR_OUTOFVIDEOMEMORY) ErrorHandler_FailWithCode(hresult, "D3D9_CreateVb");
Event_RaiseVoid(&GfxEvents_LowVRAMDetected);
}
D3D9_SetVbData(vbuffer, vertices, size, "D3D9_CreateVb - Lock", "D3D9_CreateVb - Unlock", 0);
return vbuffer;

View file

@ -68,58 +68,58 @@ static PackedCol Entity_GetCol(struct Entity* e) {
return World_IsValidPos_3I(P) ? Lighting_Col(P.X, P.Y, P.Z) : Lighting_Outside;
}
void Entity_Init(struct Entity* entity) {
entity->ModelScale = Vector3_Create1(1.0f);
entity->uScale = 1.0f;
entity->vScale = 1.0f;
void Entity_Init(struct Entity* e) {
e->ModelScale = Vector3_Create1(1.0f);
e->uScale = 1.0f;
e->vScale = 1.0f;
}
Vector3 Entity_GetEyePosition(struct Entity* entity) {
Vector3 pos = entity->Position; pos.Y += Entity_GetEyeHeight(entity); return pos;
Vector3 Entity_GetEyePosition(struct Entity* e) {
Vector3 pos = e->Position; pos.Y += Entity_GetEyeHeight(e); return pos;
}
Real32 Entity_GetEyeHeight(struct Entity* entity) {
return entity->Model->GetEyeY(entity) * entity->ModelScale.Y;
Real32 Entity_GetEyeHeight(struct Entity* e) {
return e->Model->GetEyeY(e) * e->ModelScale.Y;
}
void Entity_GetTransform(struct Entity* entity, Vector3 pos, Vector3 scale, struct Matrix* m) {
void Entity_GetTransform(struct Entity* e, Vector3 pos, Vector3 scale, struct Matrix* m) {
*m = Matrix_Identity;
struct Matrix tmp;
Matrix_Scale(&tmp, scale.X, scale.Y, scale.Z);
Matrix_MulBy(m, &tmp);
Matrix_RotateZ(&tmp, -entity->RotZ * MATH_DEG2RAD);
Matrix_RotateZ(&tmp, -e->RotZ * MATH_DEG2RAD);
Matrix_MulBy(m, &tmp);
Matrix_RotateX(&tmp, -entity->RotX * MATH_DEG2RAD);
Matrix_RotateX(&tmp, -e->RotX * MATH_DEG2RAD);
Matrix_MulBy(m, &tmp);
Matrix_RotateY(&tmp, -entity->RotY * MATH_DEG2RAD);
Matrix_RotateY(&tmp, -e->RotY * MATH_DEG2RAD);
Matrix_MulBy(m, &tmp);
Matrix_Translate(&tmp, pos.X, pos.Y, pos.Z);
Matrix_MulBy(m, &tmp);
/* return rotZ * rotX * rotY * scale * translate; */
}
void Entity_GetPickingBounds(struct Entity* entity, struct AABB* bb) {
AABB_Offset(bb, &entity->ModelAABB, &entity->Position);
void Entity_GetPickingBounds(struct Entity* e, struct AABB* bb) {
AABB_Offset(bb, &e->ModelAABB, &e->Position);
}
void Entity_GetBounds(struct Entity* entity, struct AABB* bb) {
AABB_Make(bb, &entity->Position, &entity->Size);
void Entity_GetBounds(struct Entity* e, struct AABB* bb) {
AABB_Make(bb, &e->Position, &e->Size);
}
static void Entity_ParseScale(struct Entity* entity, String scale) {
static void Entity_ParseScale(struct Entity* e, String scale) {
if (!scale.length) return;
Real32 value;
if (!Convert_TryParseReal32(&scale, &value)) return;
Real32 maxScale = entity->Model->MaxScale;
Real32 maxScale = e->Model->MaxScale;
Math_Clamp(value, 0.01f, maxScale);
entity->ModelScale = Vector3_Create1(value);
e->ModelScale = Vector3_Create1(value);
}
void Entity_SetModel(struct Entity* entity, STRING_PURE String* model) {
entity->ModelScale = Vector3_Create1(1.0f);
entity->ModelBlock = BLOCK_AIR;
void Entity_SetModel(struct Entity* e, STRING_PURE String* model) {
e->ModelScale = Vector3_Create1(1.0f);
e->ModelBlock = BLOCK_AIR;
String name, scale;
if (!String_UNSAFE_Separate(model, '|', &name, &scale)) {
@ -130,29 +130,29 @@ void Entity_SetModel(struct Entity* entity, STRING_PURE String* model) {
/* 'giant' model kept for backwards compatibility */
if (String_CaselessEqualsConst(&name, "giant")) {
name = String_FromReadonly("humanoid");
entity->ModelScale = Vector3_Create1(2.0f);
} else if (Convert_TryParseUInt8(&name, &entity->ModelBlock)) {
e->ModelScale = Vector3_Create1(2.0f);
} else if (Convert_TryParseUInt8(&name, &e->ModelBlock)) {
name = String_FromReadonly("block");
}
entity->Model = ModelCache_Get(&name);
Entity_ParseScale(entity, scale);
entity->MobTextureId = NULL;
e->Model = ModelCache_Get(&name);
Entity_ParseScale(e, scale);
e->MobTextureId = NULL;
entity->Model->RecalcProperties(entity);
Entity_UpdateModelBounds(entity);
entity->ModelIsSheepNoFur = String_CaselessEqualsConst(&name, "sheep_nofur");
e->Model->RecalcProperties(e);
Entity_UpdateModelBounds(e);
e->ModelIsSheepNoFur = String_CaselessEqualsConst(&name, "sheep_nofur");
}
void Entity_UpdateModelBounds(struct Entity* entity) {
struct Model* model = entity->Model;
model->GetCollisionSize(&entity->Size);
Vector3_Mul3By(&entity->Size, &entity->ModelScale);
void Entity_UpdateModelBounds(struct Entity* e) {
struct Model* model = e->Model;
model->GetCollisionSize(&e->Size);
Vector3_Mul3By(&e->Size, &e->ModelScale);
struct AABB* bb = &entity->ModelAABB;
struct AABB* bb = &e->ModelAABB;
model->GetPickingBounds(bb);
Vector3_Mul3By(&bb->Min, &entity->ModelScale);
Vector3_Mul3By(&bb->Max, &entity->ModelScale);
Vector3_Mul3By(&bb->Min, &e->ModelScale);
Vector3_Mul3By(&bb->Max, &e->ModelScale);
}
bool Entity_TouchesAny(struct AABB* bounds, bool (*touches_condition)(BlockID block__)) {

View file

@ -69,9 +69,9 @@ static void EnvRenderer_UpdateFogMinimal(Real32 fogDensity) {
#define LOG_005 -2.99573227355399
Real64 dist = LOG_005 / -fogDensity;
Game_SetViewDistance((Int32)dist, false);
Game_SetViewDistance((Int32)dist);
} else {
Game_SetViewDistance(Game_UserViewDistance, false);
Game_SetViewDistance(Game_UserViewDistance);
}
}
@ -837,7 +837,7 @@ static void EnvRenderer_Init(void) {
Event_RegisterVoid(&GfxEvents_ContextLost, NULL, EnvRenderer_ContextLost);
Event_RegisterVoid(&GfxEvents_ContextRecreated, NULL, EnvRenderer_ContextRecreated);
Game_SetViewDistance(Game_UserViewDistance, false);
Game_SetViewDistance(Game_UserViewDistance);
}
static void EnvRenderer_Free(void) {

View file

@ -80,53 +80,54 @@ void Event_RaiseChat(struct Event_Chat* handlers, String* msg, Int32 msgType);
void Event_RegisterChat(struct Event_Chat* handlers, void* obj, Event_Chat_Callback handler);
void Event_UnregisterChat(struct Event_Chat* handlers, void* obj, Event_Chat_Callback handler);
struct Event_Int EntityEvents_Added; /* Entity is spawned in the current world. */
struct Event_Int EntityEvents_Removed; /* Entity is despawned from the current world. */
struct Event_Int TabListEvents_Added; /* Tab list entry is created. */
struct Event_Int TabListEvents_Changed; /* Tab list entry is modified. */
struct Event_Int TabListEvents_Removed; /* Tab list entry is removed. */
struct Event_Int EntityEvents_Added; /* Entity is spawned in the current world */
struct Event_Int EntityEvents_Removed; /* Entity is despawned from the current world */
struct Event_Int TabListEvents_Added; /* Tab list entry is created */
struct Event_Int TabListEvents_Changed; /* Tab list entry is modified */
struct Event_Int TabListEvents_Removed; /* Tab list entry is removed */
struct Event_Void TextureEvents_AtlasChanged; /* Terrain atlas (terrain.png) is changed. */
struct Event_Void TextureEvents_PackChanged; /* Texture pack is changed. */
struct Event_Entry TextureEvents_FileChanged; /* File in a texture pack is changed. (terrain.png, rain.png) */
struct Event_Void TextureEvents_AtlasChanged; /* Terrain atlas (terrain.png) is changed */
struct Event_Void TextureEvents_PackChanged; /* Texture pack is changed */
struct Event_Entry TextureEvents_FileChanged; /* File in a texture pack is changed (terrain.png, rain.png) */
struct Event_Void GfxEvents_ViewDistanceChanged; /* View/fog distance is changed. */
struct Event_Void GfxEvents_ProjectionChanged; /* Projection matrix has changed. */
struct Event_Void GfxEvents_ContextLost; /* Context is destroyed after having been previously created. */
struct Event_Void GfxEvents_ContextRecreated; /* context is recreated after having been previously lost. */
struct Event_Void GfxEvents_ViewDistanceChanged; /* View/fog distance is changed */
struct Event_Void GfxEvents_LowVRAMDetected; /* Insufficient VRAM detected, need to free some GPU resources */
struct Event_Void GfxEvents_ProjectionChanged; /* Projection matrix has changed */
struct Event_Void GfxEvents_ContextLost; /* Context is destroyed after having been previously created */
struct Event_Void GfxEvents_ContextRecreated; /* Context is recreated after having been previously lost */
struct Event_Block UserEvents_BlockChanged; /* User changes a block. */
struct Event_Void UserEvents_HackPermissionsChanged; /* Hack permissions of the player changes. */
struct Event_Void UserEvents_HeldBlockChanged; /* Held block in hotbar changes. */
struct Event_Block UserEvents_BlockChanged; /* User changes a block */
struct Event_Void UserEvents_HackPermissionsChanged; /* Hack permissions of the player changes */
struct Event_Void UserEvents_HeldBlockChanged; /* Held block in hotbar changes */
struct Event_Void BlockEvents_PermissionsChanged; /* Block permissions (can place/delete) for a block changes. */
struct Event_Void BlockEvents_BlockDefChanged; /* Block definition is changed or removed. */
struct Event_Void BlockEvents_PermissionsChanged; /* Block permissions (can place/delete) for a block changes */
struct Event_Void BlockEvents_BlockDefChanged; /* Block definition is changed or removed */
struct Event_Void WorldEvents_NewMap; /* Player begins loading a new world. */
struct Event_Real WorldEvents_Loading; /* Portion of world is decompressed/generated. (Arg is progress from 0-1) */
struct Event_Void WorldEvents_MapLoaded; /* New world has finished loading, player can now interact with it. */
struct Event_Int WorldEvents_EnvVarChanged; /* World environment variable changed by player/CPE/WoM config. */
struct Event_Void WorldEvents_NewMap; /* Player begins loading a new world */
struct Event_Real WorldEvents_Loading; /* Portion of world is decompressed/generated (Arg is progress from 0-1) */
struct Event_Void WorldEvents_MapLoaded; /* New world has finished loading, player can now interact with it */
struct Event_Int WorldEvents_EnvVarChanged; /* World environment variable changed by player/CPE/WoM config */
struct Event_Void ChatEvents_FontChanged; /* User changes whether system chat font used, and when the bitmapped font texture changes. */
struct Event_Void ChatEvents_FontChanged; /* User changes whether system chat font used, and when the bitmapped font texture changes */
struct Event_Chat ChatEvents_ChatReceived; /* Raised when message is being added to chat */
struct Event_Chat ChatEvents_ChatSending; /* Raised when user sends a message */
struct Event_Int ChatEvents_ColCodeChanged; /* Raised when a colour code changes */
struct Event_Void WindowEvents_Redraw; /* Window contents invalidated, should be redrawn */
struct Event_Void WindowEvents_Moved; /* Window is moved. */
struct Event_Void WindowEvents_Resized; /* Window is resized. */
struct Event_Void WindowEvents_Closing; /* Window is about to close. */
struct Event_Void WindowEvents_Closed; /* Window has closed. */
struct Event_Void WindowEvents_VisibilityChanged; /* Visibility of the window changes. */
struct Event_Void WindowEvents_FocusChanged; /* Focus of the window changes. */
struct Event_Void WindowEvents_WindowStateChanged; /* WindowState of the window changes. */
struct Event_Void WindowEvents_Moved; /* Window is moved */
struct Event_Void WindowEvents_Resized; /* Window is resized */
struct Event_Void WindowEvents_Closing; /* Window is about to close */
struct Event_Void WindowEvents_Closed; /* Window has closed */
struct Event_Void WindowEvents_VisibilityChanged; /* Visibility of the window changed */
struct Event_Void WindowEvents_FocusChanged; /* Focus of the window changed */
struct Event_Void WindowEvents_WindowStateChanged; /* WindowState of the window changed */
struct Event_Int KeyEvents_Press; /* Raised when a character is typed. Arg is a character. */
struct Event_Int KeyEvents_Down; /* Raised when a key is pressed. Arg is a member of Key enumeration. */
struct Event_Int KeyEvents_Up; /* Raised when a key is released. Arg is a member of Key enumeration. */
struct Event_Int KeyEvents_Press; /* Raised when a character is typed. Arg is a character */
struct Event_Int KeyEvents_Down; /* Raised when a key is pressed. Arg is a member of Key enumeration */
struct Event_Int KeyEvents_Up; /* Raised when a key is released. Arg is a member of Key enumeration */
struct Event_MouseMove MouseEvents_Moved; /* Mouse position is changed. (Arg is delta from last position) */
struct Event_Int MouseEvents_Down; /* Mouse button is pressed. (Arg is MouseButton member) */
struct Event_Int MouseEvents_Up; /* Mouse button is released. (Arg is MouseButton member) */
struct Event_Real MouseEvents_Wheel; /* Mouse wheel is moved/scrolled. (Arg is wheel delta) */
struct Event_MouseMove MouseEvents_Moved; /* Mouse position is changed (Arg is delta from last position) */
struct Event_Int MouseEvents_Down; /* Mouse button is pressed (Arg is MouseButton member) */
struct Event_Int MouseEvents_Up; /* Mouse button is released (Arg is MouseButton member) */
struct Event_Real MouseEvents_Wheel; /* Mouse wheel is moved/scrolled (Arg is wheel delta) */
#endif

View file

@ -142,12 +142,7 @@ bool Game_ChangeTerrainAtlas(Bitmap* atlas) {
return true;
}
void Game_SetViewDistance(Int32 distance, bool userDist) {
if (userDist) {
Game_UserViewDistance = distance;
Options_SetInt(OPT_VIEW_DISTANCE, distance);
}
void Game_SetViewDistance(Int32 distance) {
distance = min(distance, Game_MaxViewDistance);
if (distance == Game_ViewDistance) return;
Game_ViewDistance = distance;
@ -156,6 +151,12 @@ void Game_SetViewDistance(Int32 distance, bool userDist) {
Game_UpdateProjection();
}
void Game_UserSetViewDistance(Int32 distance) {
Game_UserViewDistance = distance;
Options_SetInt(OPT_VIEW_DISTANCE, distance);
Game_SetViewDistance(distance);
}
void Game_UpdateProjection(void) {
Game_DefaultFov = Options_GetInt(OPT_FIELD_OF_VIEW, 1, 150, 70);
Camera_Active->GetProjection(&Gfx_Projection);
@ -311,6 +312,16 @@ static void Game_TextureChangedCore(void* obj, struct Stream* src, String* name)
}
}
static void Game_OnLowVRAMDetected(void) {
if (Game_UserViewDistance <= 16) ErrorHandler_Fail("Out of video memory!");
Game_UserViewDistance /= 2;
Game_UserViewDistance = max(16, Game_UserViewDistance);
ChunkUpdater_Refresh();
Game_SetViewDistance(Game_UserViewDistance);
Chat_AddRaw("&cOut of VRAM! Halving view distance..");
}
static void Game_ExtractInitialTexturePack(void) {
char texPackBuffer[STRING_SIZE];
String texPack = String_FromArray(texPackBuffer);
@ -429,6 +440,8 @@ void Game_Load(void) {
Event_RegisterVoid(&WorldEvents_NewMap, NULL, Game_OnNewMapCore);
Event_RegisterVoid(&WorldEvents_MapLoaded, NULL, Game_OnNewMapLoadedCore);
Event_RegisterEntry(&TextureEvents_FileChanged, NULL, Game_TextureChangedCore);
Event_RegisterVoid(&GfxEvents_LowVRAMDetected, NULL, Game_OnLowVRAMDetected);
Event_RegisterVoid(&WindowEvents_Resized, NULL, Game_OnResize);
Event_RegisterVoid(&WindowEvents_Closed, NULL, Game_Free);
@ -706,6 +719,8 @@ void Game_Free(void* obj) {
Event_UnregisterVoid(&WorldEvents_NewMap, NULL, Game_OnNewMapCore);
Event_UnregisterVoid(&WorldEvents_MapLoaded, NULL, Game_OnNewMapLoadedCore);
Event_UnregisterEntry(&TextureEvents_FileChanged, NULL, Game_TextureChangedCore);
Event_UnregisterVoid(&GfxEvents_LowVRAMDetected, NULL, Game_OnLowVRAMDetected);
Event_UnregisterVoid(&WindowEvents_Resized, NULL, Game_OnResize);
Event_UnregisterVoid(&WindowEvents_Closed, NULL, Game_Free);

View file

@ -79,7 +79,8 @@ void Game_GetDefaultTexturePack(STRING_TRANSIENT String* texPack);
void Game_SetDefaultTexturePack(STRING_PURE String* texPack);
bool Game_ChangeTerrainAtlas(Bitmap* atlas);
void Game_SetViewDistance(Int32 distance, bool userDist);
void Game_SetViewDistance(Int32 distance);
void Game_UserSetViewDistance(Int32 distance);
void Game_UpdateProjection(void);
void Game_Disconnect(STRING_PURE String* title, STRING_PURE String* reason);
void Game_UpdateBlock(Int32 x, Int32 y, Int32 z, BlockID block);

View file

@ -95,10 +95,10 @@ static void InputHandler_CycleDistanceForwards(Int32* viewDists, Int32 count) {
for (i = 0; i < count; i++) {
Int32 dist = viewDists[i];
if (dist > Game_UserViewDistance) {
Game_SetViewDistance(dist, true); return;
Game_UserSetViewDistance(dist); return;
}
}
Game_SetViewDistance(viewDists[0], true);
Game_UserSetViewDistance(viewDists[0]);
}
static void InputHandler_CycleDistanceBackwards(Int32* viewDists, Int32 count) {
@ -106,10 +106,10 @@ static void InputHandler_CycleDistanceBackwards(Int32* viewDists, Int32 count) {
for (i = count - 1; i >= 0; i--) {
Int32 dist = viewDists[i];
if (dist < Game_UserViewDistance) {
Game_SetViewDistance(dist, true); return;
Game_UserSetViewDistance(dist); return;
}
}
Game_SetViewDistance(viewDists[count - 1], true);
Game_UserSetViewDistance(viewDists[count - 1]);
}
bool InputHandler_SetFOV(Int32 fov, bool setZoom) {

View file

@ -22,7 +22,7 @@ void MapRenderer_RefreshChunk(Int32 cx, Int32 cy, Int32 cz) {
info->PendingDelete = true;
}
static void MapRenderer_CheckWeather(Real64 deltaTime) {
static void MapRenderer_CheckWeather(Real64 delta) {
Vector3 pos = Game_CurrentCameraPos;
Vector3I coords;
Vector3I_Floor(&coords, &pos);
@ -34,7 +34,7 @@ static void MapRenderer_CheckWeather(Real64 deltaTime) {
/* If we are under water, render weather before to blend properly */
if (!inTranslucent || WorldEnv_Weather == WEATHER_SUNNY) return;
Gfx_SetAlphaBlending(true);
EnvRenderer_RenderWeather(deltaTime);
EnvRenderer_RenderWeather(delta);
Gfx_SetAlphaBlending(false);
}
@ -126,7 +126,7 @@ static void MapRenderer_RenderNormalBatch(UInt32 batch) {
}
}
void MapRenderer_RenderNormal(Real64 deltaTime) {
void MapRenderer_RenderNormal(Real64 delta) {
if (!MapRenderer_Chunks) return;
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
Gfx_SetTexturing(true);
@ -144,7 +144,7 @@ void MapRenderer_RenderNormal(Real64 deltaTime) {
}
Gfx_DisableMipmaps();
MapRenderer_CheckWeather(deltaTime);
MapRenderer_CheckWeather(delta);
Gfx_SetAlphaTest(false);
Gfx_SetTexturing(false);
#if DEBUG_OCCLUSION
@ -212,7 +212,7 @@ static void MapRenderer_RenderTranslucentBatch(UInt32 batch) {
}
}
void MapRenderer_RenderTranslucent(Real64 deltaTime) {
void MapRenderer_RenderTranslucent(Real64 delta) {
if (!MapRenderer_Chunks) return;
/* First fill depth buffer */
@ -251,7 +251,7 @@ void MapRenderer_RenderTranslucent(Real64 deltaTime) {
/* If we weren't under water, render weather after to blend properly */
if (!inTranslucent && WorldEnv_Weather != WEATHER_SUNNY) {
Gfx_SetAlphaTest(true);
EnvRenderer_RenderWeather(deltaTime);
EnvRenderer_RenderWeather(delta);
Gfx_SetAlphaTest(false);
}
Gfx_SetAlphaBlending(false);

View file

@ -49,6 +49,6 @@ struct ChunkPartInfo* MapRenderer_PartsTranslucent;
struct ChunkInfo* MapRenderer_GetChunk(Int32 cx, Int32 cy, Int32 cz);
void MapRenderer_RefreshChunk(Int32 cx, Int32 cy, Int32 cz);
void MapRenderer_RenderNormal(Real64 deltaTime);
void MapRenderer_RenderTranslucent(Real64 deltaTime);
void MapRenderer_RenderNormal(Real64 delta);
void MapRenderer_RenderTranslucent(Real64 delta);
#endif

View file

@ -2215,7 +2215,7 @@ static void ClassicOptionsScreen_GetViewDist(STRING_TRANSIENT String* v) {
static void ClassicOptionsScreen_SetViewDist(STRING_PURE String* v) {
UInt32 raw = Utils_ParseEnum(v, 0, ViewDist_Names, ViewDist_Count);
Int32 dist = raw == ViewDist_Far ? 512 : (raw == ViewDist_Normal ? 128 : (raw == ViewDist_Short ? 32 : 8));
Game_SetViewDistance(dist, true);
Game_UserSetViewDistance(dist);
}
static void ClassicOptionsScreen_GetPhysics(STRING_TRANSIENT String* v) { Menu_GetBool(v, Physics_Enabled); }
@ -2398,7 +2398,7 @@ struct Screen* EnvSettingsScreen_MakeInstance(void) {
*--------------------------------------------------GraphicsOptionsScreen--------------------------------------------------*
*#########################################################################################################################*/
static void GraphicsOptionsScreen_GetViewDist(STRING_TRANSIENT String* v) { String_AppendInt32(v, Game_ViewDistance); }
static void GraphicsOptionsScreen_SetViewDist(STRING_PURE String* v) { Game_SetViewDistance(Menu_Int32(v), true); }
static void GraphicsOptionsScreen_SetViewDist(STRING_PURE String* v) { Game_UserSetViewDistance(Menu_Int32(v)); }
static void GraphicsOptionsScreen_GetSmooth(STRING_TRANSIENT String* v) { Menu_GetBool(v, Game_SmoothLighting); }
static void GraphicsOptionsScreen_SetSmooth(STRING_PURE String* v) {

View file

@ -979,7 +979,7 @@ static void CPE_EnvSetMapAppearance(UInt8* data) {
WorldEnv_SetCloudsHeight((Int16)Stream_GetU16_BE(&data[68]));
Int16 maxViewDist = (Int16)Stream_GetU16_BE(&data[70]);
Game_MaxViewDistance = maxViewDist <= 0 ? 32768 : maxViewDist;
Game_SetViewDistance(Game_UserViewDistance, false);
Game_SetViewDistance(Game_UserViewDistance);
}
static void CPE_EnvWeatherType(UInt8* data) {
@ -1087,7 +1087,7 @@ static void CPE_SetMapEnvProperty(UInt8* data) {
case 4:
Math_Clamp(value, -0x7FFF, 0x7FFF);
Game_MaxViewDistance = value <= 0 ? 32768 : value;
Game_SetViewDistance(Game_UserViewDistance, false); break;
Game_SetViewDistance(Game_UserViewDistance); break;
case 5:
WorldEnv_SetCloudsSpeed(value / 256.0f); break;
case 6: