// update dynamic entities private void UpdateDynamic(object o) { if (Monitor.TryEnter(_areaManagerSyncRoot)) { try { var state = new DynamicUpdateState { ElapsedTime = _lastUpdate == new UtopiaTime() ? UtopiaTimeSpan.Zero : _server.Clock.Now - _lastUpdate, CurrentTime = _server.Clock.Now }; state.RealTime = _server.Clock.GameToReal(state.ElapsedTime); _lastUpdate = _server.Clock.Now; Update(state); } finally { Monitor.Exit(_areaManagerSyncRoot); } } else { logger.Warn("Warning! Server is overloaded. Try to decrease dynamic entities count"); } }
public void CheckGrowing() { var entityGrowingManager = new EntityGrowingManager(null); var random = new Random(1); var entity = new PlantGrowingEntity(); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromHours(1) }); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromHours(1) }); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromHours(1) }); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromHours(1) }); entity.LastGrowUpdate = new UtopiaTime() + UtopiaTimeSpan.FromMinutes(1); var now = new UtopiaTime() + UtopiaTimeSpan.FromHours(2.5); entityGrowingManager.EntityGrowCheck(now, entity, null, random); Assert.AreEqual(2, entity.CurrentGrowLevelIndex); entity = new PlantGrowingEntity(); entity.GrowingSeasons.Add(UtopiaTime.TimeConfiguration.Seasons[0].Name); entity.GrowingSeasons.Add(UtopiaTime.TimeConfiguration.Seasons[2].Name); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromDays(10) }); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromDays(10) }); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromDays(10) }); entity.GrowLevels.Add(new GrowLevel { GrowTime = UtopiaTimeSpan.FromDays(10) }); entity.LastGrowUpdate = new UtopiaTime() + UtopiaTimeSpan.FromMinutes(1); now = new UtopiaTime() + UtopiaTimeSpan.FromMinutes(50); entityGrowingManager.EntityGrowCheck(now, entity, null, random); entity.LastGrowUpdate = now; Assert.AreEqual(0, entity.CurrentGrowLevelIndex); now = new UtopiaTime() + UtopiaTimeSpan.FromYears(1); entityGrowingManager.EntityGrowCheck(now, entity, null, random); entity.LastGrowUpdate = now; Assert.AreEqual(1, entity.CurrentGrowLevelIndex); now = new UtopiaTime() + UtopiaTimeSpan.FromYears(1) + UtopiaTimeSpan.FromMinutes(1); entityGrowingManager.EntityGrowCheck(now, entity, null, random); entity.LastGrowUpdate = now; Assert.AreEqual(2, entity.CurrentGrowLevelIndex); }
private WeatherMessage UpdateWeather() { UtopiaTime now = _server.Clock.Now; if (TimeConfiguration.Seasons.Count == 0) { return(new WeatherMessage()); } var growing = now.Day / ((float)TimeConfiguration.DaysPerSeason / 2) <= 1; Season s1, s2; float power; var seasonIndex = now.SeasonIndex; if (growing) { var s1Index = seasonIndex - 1 < 0 ? TimeConfiguration.Seasons.Count - 1 : seasonIndex - 1; s1 = TimeConfiguration.Seasons[s1Index]; s2 = TimeConfiguration.Seasons[seasonIndex]; power = now.Day / ((float)TimeConfiguration.DaysPerSeason) + 0.5f; } else { var s2Index = seasonIndex + 1 >= TimeConfiguration.Seasons.Count ? 0 : seasonIndex + 1; s1 = TimeConfiguration.Seasons[seasonIndex]; s2 = TimeConfiguration.Seasons[s2Index]; power = now.Day / ((float)TimeConfiguration.DaysPerSeason) - 0.5f; } var temperature = Lerp(s1.Temperature, s2.Temperature, power); var moisture = Lerp(s1.Moisture, s2.Moisture, power); var msg = new WeatherMessage { MoistureOffset = moisture, TemperatureOffset = temperature }; return(msg); }
private void AssignTimeAndFactor(double timeFactor, UtopiaTime worldDatetime) { TimeFactor = (float)timeFactor; _baseUtopiaTime = worldDatetime; _utopiaLastRealTimeUpdate = DateTime.Now; _clockTime = -1; var prevFrozen = FrozenTime; FrozenTime = false; FTSUpdate(new GameTime()); FrozenTime = prevFrozen; float y = (float)Math.Cos(ClockTime.ClockTimeNormalized * MathHelper.TwoPi); float x = (float)Math.Sin(ClockTime.ClockTimeNormalized * MathHelper.TwoPi); logger.Info("SunLight Vector is {0}", new SharpDX.Vector3(x, y, 0)); }
private void GrowingLookup(UtopiaTime gametime) { var random = new Random(); foreach (var chunk in _server.LandscapeManager.GetBufferedChunks()) { var growingEntities = chunk.Entities.OfType <GrowingEntity>().ToList(); foreach (var entity in growingEntities) { var now = _server.Clock.Now; // fix time cheat if (now > entity.LastGrowUpdate) { EntityGrowCheck(_server.Clock.Now, entity, chunk, random); } entity.LastGrowUpdate = now; } } }
/// <summary> /// Method responsible to do chunk spawn logic /// </summary> private void UtopiaSpawningLookup(UtopiaTime gametime) { //Logic to "Randomize" and limit the number of chunk to update per cycle ====================================================== //Get the chunks that are under server management and are candidate for a refresh ! var serverChunksToUpdate = _landscapeManager.GetBufferedChunks().Where(x => (gametime - x.LastSpawningRefresh) > _chunkUpdateCycle).ToList(); //Get the chunk not in the processing list => New chunk to process var newChunks = serverChunksToUpdate.Where(x => _chunks4Processing.Contains(x) == false).ToList(); if (newChunks.Count > 0) { _chunks4Processing.AddRange(newChunks); _chunks4Processing.Shuffle(); //Shuffle all chunks that must be updated. } //Get the chunk not handled anymore by the server and remove them from the processing list _chunks4Processing.RemoveAll(c => serverChunksToUpdate.Contains(c) == false); //Process _maxChunkRefreshPerCycle at maximum foreach (var chunk in _chunks4Processing.Take(_maxChunkRefreshPerCycle)) { SpawnBiomeEntities(gametime, chunk); TreeSoulUpdate(chunk); chunk.LastSpawningRefresh = gametime; } if (_chunks4Processing.Count < _maxChunkRefreshPerCycle) { _chunks4Processing.Clear(); } else { _chunks4Processing.RemoveRange(0, _maxChunkRefreshPerCycle); } }
public void EntityGrowCheck(UtopiaTime now, GrowingEntity entity, ServerChunk chunk, Random random) { if (entity.LastGrowUpdate.IsZero) { return; } var checkTimeSpan = now - entity.LastGrowUpdate; bool updated; bool rotten; // grow time left at the current season var tillTheEndOfSeason = UtopiaTimeSpan.FromSeasons(1d - entity.LastGrowUpdate.TotalSeasons % 1d); if (checkTimeSpan <= tillTheEndOfSeason) { // small grow update updated = GrowSeasonLogic(entity, now.Season, checkTimeSpan, random, chunk, out rotten); if (rotten) { return; } } else { // grow at the end of the first season updated = GrowSeasonLogic(entity, now.Season, tillTheEndOfSeason, random, chunk, out rotten); if (rotten) { return; } // align time to the beginning of next season checkTimeSpan -= tillTheEndOfSeason; while (checkTimeSpan.TotalSeconds > 0) { var seasonCheckSpan = checkTimeSpan.TotalSeasons > 0 ? UtopiaTimeSpan.FromSeasons(1) : checkTimeSpan; updated = GrowSeasonLogic(entity, (now - checkTimeSpan).Season, seasonCheckSpan, random, chunk, out rotten) || updated; if (rotten) { return; } checkTimeSpan -= seasonCheckSpan; } } if (updated) { if (entity is PlantGrowingEntity) { if (chunk != null) { chunk.Entities.RemoveById(entity.StaticId); chunk.Entities.Add(entity); } } var tree = entity as TreeGrowingEntity; if (tree != null) { var treeBlueprint = _server.EntityFactory.Config.TreeBluePrintsDico[tree.TreeTypeId]; if (tree.CurrentGrowTime > treeBlueprint.GrowTime) { // the tree is ready var model = VoxelModel.GenerateTreeModel(tree.TreeRndSeed, treeBlueprint); // create tree blocks var rootOffset = model.States[0].PartsStates[0].Translation; var cursor = _server.LandscapeManager.GetCursor(tree.Position); var frame = model.Frames[0]; var range = new Range3I(new Vector3I(), frame.BlockData.ChunkSize); using (cursor.TransactionScope()) { foreach (var position in range) { var value = frame.BlockData.GetBlock(position); if (value == 0) { continue; } var blockType = value == 1 ? treeBlueprint.TrunkBlock : treeBlueprint.FoliageBlock; var worldPos = (Vector3I)(tree.Position + rootOffset) + position; cursor.GlobalPosition = worldPos; if (cursor.Read() == WorldConfiguration.CubeId.Air) { cursor.Write(blockType); } } } // create tree soul var soul = _server.EntityFactory.CreateEntity <TreeSoul>(); soul.Position = tree.Position; soul.TreeRndSeed = tree.TreeRndSeed; soul.TreeTypeId = tree.TreeTypeId; chunk.Entities.Add(soul); // remove the growing tree chunk.Entities.RemoveById(tree.StaticId); } else { // just make the model bigger tree.Scale = (float)tree.CurrentGrowTime.TotalSeconds / treeBlueprint.GrowTime.TotalSeconds; chunk.Entities.RemoveById(tree.StaticId); chunk.Entities.Add(tree); } } } }
/// <summary> /// Create new instance of the Server class /// </summary> public ServerCore( XmlSettingsManager <ServerSettings> settingsManager, WorldGenerator worldGenerator, IUsersStorage usersStorage, IChunksStorage chunksStorage, IEntityStorage entityStorage, ICustomStorage customStorage, EntityFactory entityFactory, WorldParameters wp ) { // dependency injection SettingsManager = settingsManager; UsersStorage = usersStorage; EntityStorage = entityStorage; CustomStorage = customStorage; EntityFactory = entityFactory; WorldParameters = wp; if (SettingsManager.Settings == null) { SettingsManager.Load(); } var settings = SettingsManager.Settings; ConnectionManager = new ConnectionManager(SettingsManager.Settings.ServerPort); Scheduler = new ScheduleManager(); UtopiaTime startTime = CustomStorage.GetVariable <UtopiaTime>("GameTimeElapsed"); Clock = new Clock(this, startTime, TimeSpan.FromMinutes(20)); LandscapeManager = new ServerLandscapeManager( this, chunksStorage, worldGenerator, EntityFactory, settings.ChunkLiveTimeMinutes, settings.CleanUpInterval, settings.SaveInterval, settings.ChunksCountLimit, wp); EntityManager = new EntityManager(this); AreaManager = new AreaManager(this); DynamicIdHelper.SetMaxExistsId(EntityStorage.GetMaximumId()); Services = new ServiceManager(this); PerformanceManager = new PerformanceManager(AreaManager); CommandsManager = new CommandsManager(this); ChatManager = new ChatManager(this); GlobalStateManager = new GlobalStateManager(this); LoginManager = new LoginManager(this, EntityFactory); EntitySpawningManager = new EntitySpawningManager(this, worldGenerator.EntitySpawningControler); EntityGrowingManager = new Managers.EntityGrowingManager(this); }
private void PerDayTrigger(UtopiaTime gametime) { // each day we will recalculate temperature and humidity values _lastMessage = UpdateWeather(); _server.ConnectionManager.Broadcast(_lastMessage); }
private void SpawnBiomeEntities(UtopiaTime gametime, ServerChunk chunk) { var chunkBiome = _configuration.ProcessorParam.Biomes[chunk.BlockData.ChunkMetaData.ChunkMasterBiomeType]; foreach (var spawnableEntity in chunkBiome.SpawnableEntities) { bool isStaticEntity = _configuration.BluePrints[spawnableEntity.BluePrintId] is IStaticEntity; //Remark : isChunkGenerationSpawning is set to true for static entities, and false for dynamic entities, maybe worth renaming the properties //The aim of it is to avoid dynamic entity creation at chunk generation time (Pure chunk). //Apply creation constaint : //1) if static entity with is isWildChunkNeeded and chunk is not wild => Do nothing if (spawnableEntity.IsWildChunkNeeded && chunk.BlockData.ChunkMetaData.IsWild == false) { continue; } if (chunk.PureGenerated && isStaticEntity) { continue; } var isDayTime = gametime.TimeOfDay > UtopiaTimeSpan.FromHours(8) && gametime.TimeOfDay < UtopiaTimeSpan.FromHours(20); // check daytime constraints if (!spawnableEntity.SpawningDayTime.HasFlag(ChunkSpawningDayTime.Day) && isDayTime) { continue; } if (!spawnableEntity.SpawningDayTime.HasFlag(ChunkSpawningDayTime.Night) && !isDayTime) { continue; } // check season constraint var weatherService = _server.Services.GetService <WeatherService>(); if (weatherService != null && weatherService.CurrentSeason != null && spawnableEntity.SpawningSeasons.Count > 0 && !spawnableEntity.SpawningSeasons.Contains(weatherService.CurrentSeason.Name)) { continue; } ByteChunkCursor chunkCursor = new ByteChunkCursor(chunk.BlockData.GetBlocksBytes(), chunk.BlockData.ColumnsInfo); // ==> Maybe worth to automaticaly create this specialize cursor at server chunk creation ? Multithreading problem ? //It is only use for reading chunk block data in fast way Vector3D entityLocation; if (_entitySpawningControler.TryGetSpawnLocation(spawnableEntity, chunk, chunkCursor, _fastRandom, out entityLocation)) { var entity = _server.EntityFactory.CreateFromBluePrint(spawnableEntity.BluePrintId); var staticEntity = entity as IStaticEntity; if (staticEntity != null) { //Check the maximum amount of static entities; int maxEntityAmount; chunk.BlockData.ChunkMetaData.InitialSpawnableEntitiesAmount.TryGetValue(spawnableEntity.BluePrintId, out maxEntityAmount); if (maxEntityAmount == 0) { continue; } if (chunk.Entities.Where(e => e.BluePrintId == spawnableEntity.BluePrintId) .CountAtLeast(maxEntityAmount)) { continue; } staticEntity.Position = entityLocation; var cursor = _server.LandscapeManager.GetCursor(entityLocation); logger.Debug("Spawning new static entity : {0} at location {1}", staticEntity.Name, entityLocation); var blockLinkedItem = staticEntity as IBlockLinkedEntity; if (blockLinkedItem != null) { blockLinkedItem.LinkedCube = (Vector3I)entityLocation + Vector3I.Down; } cursor.AddEntity(staticEntity); } var charEntity = entity as CharacterEntity; if (charEntity != null) { if (DisableNPCSpawn) { continue; } var radius = Math.Max(8, spawnableEntity.DynamicEntitySpawnRadius); if ( _server.AreaManager.EnumerateAround(entityLocation, radius) .CountAtLeast(spawnableEntity.MaxEntityAmount)) { continue; } charEntity.Position = entityLocation; logger.Debug("Spawning new dynamic entity : {0} at location {1}", charEntity.Name, entityLocation); _server.EntityManager.AddNpc(charEntity); } } } }