/// <inheritdoc /> public void AddChunk(ChunkColumn chunk, ChunkCoordinates position, bool doUpdates = false) { if (CancellationToken.IsCancellationRequested) { return; } //chunk.CalculateHeight(); if (chunk.IsNew) { SkyLightCalculator.RecalcSkyLight(chunk, World); BlockLightCalculations.Recalculate(chunk); } foreach (var blockEntity in chunk.GetBlockEntities) { var coordinates = new BlockCoordinates(blockEntity.X, blockEntity.Y, blockEntity.Z); //World.SetBlockEntity(coordinates.X, coordinates.Y, coordinates.Z, blockEntity); World.EntityManager.AddBlockEntity(coordinates, blockEntity); } Chunks.AddOrUpdate( position, coordinates => chunk, (coordinates, column) => { if (!ReferenceEquals(column, chunk)) { column.Dispose(); } return(chunk); }); ScheduleChunkUpdate(position, ScheduleType.Full); //UpdateQueue.Enqueue(position); }
private bool ProcessLighting(ChunkCoordinates[] renderedChunks) { bool processed = false; if (BlockLightCalculations.TryProcess( blockCoordinates => { return(Chunks.ContainsKey((ChunkCoordinates)blockCoordinates)); }, out BlockCoordinates coordinates)) { if (coordinates.Y < 0 || coordinates.Y >= 256) { return(false); } ChunkCoordinates cc = (ChunkCoordinates)coordinates; if (TryGetChunk(cc, out var c)) { c.GetSection(coordinates.Y)?.SetBlockLightScheduled( coordinates.X & 0x0f, coordinates.Y - 16 * (coordinates.Y >> 4), coordinates.Z & 0x0f, true); //ScheduleChunkUpdate(cc, ScheduleType.Lighting); } return(true); } return(false); }
public void RecalculateLight(Level level, AnvilWorldProvider wp) { while (wp.LightSources.Count > 0) { var block = wp.LightSources.Dequeue(); block = level.GetBlock(block.Coordinates); BlockLightCalculations.Calculate(level, block); } }
public static void RecalculateLight(Level level, AnvilWorldProvider anvilWorldProvider) { SkyLightCalculations.Calculate(level); while (anvilWorldProvider.LightSources.Count > 0) { var block = anvilWorldProvider.LightSources.Dequeue(); BlockLightCalculations.Calculate(level, block.Coordinates); } }
public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world) { Graphics = graphics; World = world; Options = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions; Resources = serviceProvider.GetRequiredService <ResourceManager>(); var stillAtlas = Resources.Atlas.GetStillAtlas(); var fogStart = 0; Shaders = new RenderingShaders(Graphics); Shaders.SetTextures(stillAtlas); Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0)); RenderDistance = Options.VideoOptions.RenderDistance; Options.VideoOptions.RenderDistance.Bind( (value, newValue) => { RenderDistance = newValue; }); Chunks = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>(); CancellationToken = new CancellationTokenSource(); BlockLightCalculations = new BlockLightCalculations((World)world); SkyLightCalculator = new SkyLightCalculations(); Func <ChunkCoordinates, ChunkCoordinates, int> orderingTool = (a, b) => { var pos = new ChunkCoordinates(World.Camera.Position); var aDistance = a.DistanceTo(pos); var bDistance = b.DistanceTo(pos); if (aDistance < bDistance) { return(-1); } if (bDistance > aDistance) { return(1); } return(0); }; UpdateQueue = new FancyQueue <ChunkCoordinates>(); UpdateBorderQueue = new FancyQueue <ChunkCoordinates>(); FastUpdateQueue = new FancyQueue <ChunkCoordinates>(); }
public static void RecalculateBlockLight(Level level, AnvilWorldProvider wp) { Queue <Block> sources = new Queue <Block>(wp.LightSources); while (sources.Count > 0) { var block = sources.Dequeue(); if (block == null) { continue; } block = level.GetBlock(block.Coordinates); BlockLightCalculations.Calculate(level, block); } }
/// <inheritdoc /> public void Dispose() { if (_disposed) { return; } try { //Graphics?.Dispose(); BlockLightCalculations?.Dispose(); BlockLightCalculations = null; SkyLightCalculator?.Dispose(); SkyLightCalculator = null; _renderSampler.Dispose(); CancellationToken.Cancel(); UpdateQueue.Clear(); FastUpdateQueue.Clear(); UpdateBorderQueue.Clear(); foreach (var chunk in Chunks) { chunk.Value.Dispose(); } Chunks.Clear(); foreach (var rendered in _renderedChunks) { rendered.Dispose(); } _renderedChunks = null; } finally { _disposed = true; } }
/// <inheritdoc /> public void RemoveChunk(ChunkCoordinates position, bool dispose = true) { BlockLightCalculations.Remove(position); if (Chunks.TryRemove(position, out var column)) { foreach (var blockEntity in column.GetBlockEntities) { World.EntityManager.RemoveBlockEntity( new BlockCoordinates((column.X << 4) + blockEntity.X, blockEntity.Y, (column.Z << 4) + blockEntity.Z)); } UpdateQueue.Remove(position); UpdateBorderQueue.Remove(position); if (dispose) { column.Dispose(); } } }
/// <inheritdoc /> public void AddChunk(ChunkColumn chunk, ChunkCoordinates position, bool doUpdates = false) { //chunk.CalculateHeight(); Chunks.AddOrUpdate( position, coordinates => chunk, (coordinates, column) => { if (!ReferenceEquals(column, chunk)) { column.Dispose(); } return(chunk); }); if (chunk.IsNew) { var chunkpos = new BlockCoordinates(position.X << 4, 0, position.Z << 4); foreach (var ls in chunk.GetLightSources()) { BlockLightCalculations.Enqueue(chunkpos + ls); } //SkyLightCalculations s = new SkyLightCalculations(); //SkyLightCalculator.Calculate(chunk, position); } foreach (var blockEntity in chunk.GetBlockEntities) { var coordinates = new BlockCoordinates(blockEntity.X, blockEntity.Y, blockEntity.Z); //World.SetBlockEntity(coordinates.X, coordinates.Y, coordinates.Z, blockEntity); World.EntityManager.AddBlockEntity(coordinates, blockEntity); } ScheduleChunkUpdate(position, ScheduleType.Full); //UpdateQueue.Enqueue(position); }
public void NewArena(MapInfo map) { lock (LevelSync) { AnvilWorldProvider l; if (OnlyRead) { l = map.ProviderCache; } else { l = map.ProviderCache.Clone() as AnvilWorldProvider; } int id = LevelCount; if (LevelPoolId.Count > 0) { id = LevelPoolId.First(); LevelPoolId.Remove(id); } else { LevelCount++; id = LevelCount; } var level = new xCoreLevel(l, Game.Context.Server.LevelManager.EntityManager, Game, map, id); LevelCount++; level.Initialize(); SkyLightCalculations.Calculate(level); while (l.LightSources.Count > 0) { var block = l.LightSources.Dequeue(); block = level.GetBlock(block.Coordinates); BlockLightCalculations.Calculate(level, block); } Game.Initialization(level); Levels.Add(level); } }
public void ResetMap() { //if (_worldProvider == null) throw new Exception($"Can not get level from the WorldProvider"); AnvilWorldProvider worldProvider = WorldProvider as AnvilWorldProvider; //worldProvider._chunkCache.Clear(); //worldProvider = Map.ProviderCache.Clone() as AnvilWorldProvider; ConcurrentDictionary <ChunkCoordinates, ChunkColumn> chunkCache = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>(); foreach (KeyValuePair <ChunkCoordinates, ChunkColumn> valuePair in Map.ProviderCache._chunkCache) { chunkCache.TryAdd(valuePair.Key, (ChunkColumn)valuePair.Value?.Clone()); } worldProvider._chunkCache.Clear(); worldProvider._chunkCache = chunkCache; SkyLightCalculations.Calculate(this); while (worldProvider.LightSources.Count > 0) { var block = worldProvider.LightSources.Dequeue(); block = this.GetBlock(block.Coordinates); BlockLightCalculations.Calculate(this, block); } //WorldProvider. = worldProvider; }
public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world) { Graphics = graphics; World = world; Options = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions; Resources = serviceProvider.GetRequiredService <ResourceManager>(); var stillAtlas = Resources.Atlas.GetStillAtlas(); var fogStart = 0; Shaders = new RenderingShaders(Graphics); Shaders.SetTextures(stillAtlas); Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0)); _renderSampler.MaxMipLevel = stillAtlas.LevelCount; RenderDistance = Options.VideoOptions.RenderDistance; Options.VideoOptions.RenderDistance.Bind( (value, newValue) => { RenderDistance = newValue; }); Chunks = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>(); CancellationToken = new CancellationTokenSource(); BlockLightCalculations = new BlockLightCalculations(world, CancellationToken.Token); SkyLightCalculator = new SkyLightCalculations(CancellationToken.Token); UpdateQueue = new FancyQueue <ChunkCoordinates>(); UpdateBorderQueue = new FancyQueue <ChunkCoordinates>(); FastUpdateQueue = new FancyQueue <ChunkCoordinates>(); }
private bool ProcessQueue() { if (Interlocked.Read(ref _threadsRunning) >= Options.VideoOptions.ChunkThreads) { return(false); } FancyQueue <ChunkCoordinates> queue = FastUpdateQueue; if (queue.IsEmpty) { queue = UpdateQueue; } if (queue.IsEmpty) { queue = UpdateBorderQueue; } if (queue.IsEmpty || Interlocked.Read(ref _threadsRunning) >= queue.Count) { return(false); } Interlocked.Increment(ref _threadsRunning); ThreadPool.QueueUserWorkItem( oo => { try { while (queue.TryDequeue(out var chunkCoordinates, cc => { return(IsWithinView(cc, World.Camera)); })) { if (TryGetChunk(chunkCoordinates, out var chunk)) { if (!Monitor.TryEnter(chunk.UpdateLock, 0)) { continue; } try { if (BlockLightCalculations.HasEnqueued(chunkCoordinates)) { BlockLightCalculations.Process(chunkCoordinates); } //SkyLightCalculator.TryProcess(chunkCoordinates); bool newChunk = chunk.IsNew; if (newChunk) { SkyLightCalculator.RecalcSkyLight(chunk, World); } chunk.UpdateBuffer(Graphics, World, chunkCoordinates.DistanceTo(new ChunkCoordinates(World.Camera.Position)) <= RenderDistance / 2); if (newChunk) { ScheduleChunkUpdate(new ChunkCoordinates(chunk.X + 1, chunk.Z), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X - 1, chunk.Z), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z + 1), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z - 1), ScheduleType.Border | ScheduleType.Lighting); } } finally { //Scheduled.Remove(chunkCoordinates); Monitor.Exit(chunk.UpdateLock); } } if (queue != FastUpdateQueue && !FastUpdateQueue.IsEmpty) { queue = FastUpdateQueue; } else if (queue == FastUpdateQueue && FastUpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateBorderQueue && !UpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateQueue && UpdateQueue.IsEmpty) { queue = UpdateBorderQueue; } } } finally { Interlocked.Decrement(ref _threadsRunning); } }); return(true); }
public static void RecalculateBlockLight(Level level, AnvilWorldProvider wp) { var sources = wp.LightSources.ToArray(); Parallel.ForEach(sources, block => { BlockLightCalculations.Calculate(level, block.Coordinates); }); }
private bool ProcessQueue() { var maxThreads = Options.VideoOptions.ChunkThreads.Value; if (Interlocked.Read(ref _threadsRunning) >= maxThreads) { return(false); } FancyQueue <ChunkCoordinates> queue = FastUpdateQueue; if (queue.IsEmpty) { queue = UpdateQueue; } if (queue.IsEmpty) { queue = UpdateBorderQueue; } //maxThreads = Math.Max(1, Math.Min(Options.VideoOptions.ChunkThreads, EnqueuedChunkUpdates / 4)); if (queue.IsEmpty || Interlocked.Read(ref _threadsRunning) >= maxThreads) { return(false); } //if (Interlocked.Read(ref _threadsRunning) ) Interlocked.Increment(ref _threadsRunning); ThreadPool.QueueUserWorkItem( oo => { try { while (!CancellationToken.IsCancellationRequested && queue.TryDequeue(out var chunkCoordinates, cc => IsWithinView(cc, World.Camera))) { if (TryGetChunk(chunkCoordinates, out var chunk)) { if (!Monitor.TryEnter(chunk.UpdateLock, 0)) { continue; } try { bool newChunk = chunk.IsNew; if (BlockLightCalculations != null) { if (newChunk) { //BlockLightCalculations.Recalculate(chunk); } if (BlockLightCalculations.HasEnqueued(chunkCoordinates)) { BlockLightCalculations.Process(chunkCoordinates); } } //SkyLightCalculator.TryProcess(chunkCoordinates); if (SkyLightCalculator != null) { if (newChunk) { SkyLightCalculator.RecalcSkyLight(chunk, World); } } chunk.UpdateBuffer(Graphics, World); /* if (newChunk) * { * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X + 1, chunk.Z), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X - 1, chunk.Z), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z + 1), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z - 1), ScheduleType.Border); * }*/ } finally { Scheduled.Remove(chunkCoordinates); Monitor.Exit(chunk.UpdateLock); } } if (queue != FastUpdateQueue && !FastUpdateQueue.IsEmpty) { queue = FastUpdateQueue; } else if (queue == FastUpdateQueue && FastUpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateBorderQueue && !UpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateQueue && UpdateQueue.IsEmpty) { queue = UpdateBorderQueue; } } } finally { Interlocked.Decrement(ref _threadsRunning); } }); return(true); }
private bool ProcessLighting() { return(BlockLightCalculations.Process( Chunks.FirstOrDefault(x => BlockLightCalculations.HasEnqueued(x.Key)).Key)); }
public LevelPoolGame(xCoreGames core, xCoreInterface game, bool onlyread, bool parse) { Random rnd = new Random(); var timings = new Stopwatch(); timings.Start(); string basepath = Config.GetProperty("PluginDirectory", "Plugins") + "\\" + game.NameGame; for (int id = 1; id <= game.ArenaLoaded; id++) { if (Maps.Count == 0) { DirectoryInfo dirInfo = new DirectoryInfo(basepath); foreach (var dir in dirInfo.GetDirectories()) { var provider = new AnvilWorldProvider(basepath + "\\" + dir.Name); var cfg = File.ReadAllText(basepath + "\\" + dir.Name + "\\config.json"); JObject jobj = JObject.Parse(cfg); Maps.Add(dir.Name, new MapInfo(dir.Name, jobj)); Maps[dir.Name].ProviderCache = provider; Maps[dir.Name].ProviderCache.Initialize(); Maps[dir.Name].ProviderCache.PruneAir(); Maps[dir.Name].ProviderCache.MakeAirChunksAroundWorldToCompensateForBadRendering(); } } string map = Maps.Keys.ElementAt(rnd.Next(0, Maps.Keys.Count - 1)); Level levelkey = Levels.FirstOrDefault(l => l.LevelId.Equals(game.NameGame + id, StringComparison.InvariantCultureIgnoreCase)); if (levelkey == null) { AnvilWorldProvider provider; //provider = Maps[map].ProviderCache; //if (!Maps[map].ProviderBool) //{ if (onlyread) { provider = Maps[map].ProviderCache; } else { provider = Maps[map].ProviderCache.Clone() as AnvilWorldProvider; } //} var level = new xCoreLevel(provider, game.Context.Server.LevelManager.EntityManager, game, Maps[map], LevelCount); LevelCount++; level.Initialize(); SkyLightCalculations.Calculate(level); while (provider.LightSources.Count > 0) { var block = provider.LightSources.Dequeue(); block = level.GetBlock(block.Coordinates); BlockLightCalculations.Calculate(level, block); } if (parse) { int X = Maps[map].Center.X; int Z = Maps[map].Center.Z; List <BlockCoordinates> BE = new List <BlockCoordinates>(); if (Maps[map].CacheBlockEntites == null) { int startX = Math.Min(X - 256, X + 256); int endX = Math.Max(X - 256, X + 256); int startY = Math.Min(11, 129); int endY = Math.Max(11, 129); int startZ = Math.Min(Z - 256, Z + 256); int endZ = Math.Max(Z - 256, Z + 256); for (int x = startX; x <= endX; ++x) { for (int y = startY; y <= endY; ++y) { for (int z = startZ; z <= endZ; ++z) { var bc = new BlockCoordinates(x, y, z); BlockEntity blockentity; if ((blockentity = level.GetBlockEntity(bc)) != null) { if (blockentity is ChestBlockEntity) { if (!BE.Contains(blockentity.Coordinates)) { BE.Add(blockentity.Coordinates); } } else if (blockentity is Sign) { CleanSignText(((Sign)blockentity).GetCompound(), "Text1"); CleanSignText(((Sign)blockentity).GetCompound(), "Text2"); CleanSignText(((Sign)blockentity).GetCompound(), "Text3"); CleanSignText(((Sign)blockentity).GetCompound(), "Text4"); BE.Add(bc); } } } } } for (int x = startX; x <= endX; ++x) { for (int z = startZ; z <= endZ; ++z) { var bc = new BlockCoordinates(x, 127, z); MiNET.Blocks.Block b = level.GetBlock(bc); if (b.Id == 95) { level.SetAir(bc, false); } } } } if (Maps[map].CacheBlockEntites == null) { Maps[map].CacheBlockEntites = BE; } } game.Initialization(level); Levels.Add(level); } } Core = core; Game = game; OnlyRead = onlyread; timings.Stop(); Log.Info("Loaded " + Levels.Count + " arenas . Load time " + timings.ElapsedMilliseconds + " ms"); _tickerHighPrecisionTimer = new Timer(QueueTimer, null, 0, 1000); }