// TODO: Refactor constructors public Level(string directory) { Difficulty = Difficulty.Normal; Name = "world"; LevelDirectory = directory; if (!Directory.Exists(LevelDirectory)) Directory.CreateDirectory(LevelDirectory); // Load from level.dat if (!File.Exists(Path.Combine(LevelDirectory, "level.dat"))) { WorldGenerator = DefaultGenerator; WorldGenerator.Initialize(this); SpawnPoint = WorldGenerator.SpawnPoint; World = new World(this, WorldGenerator, Path.Combine(directory, "region")); SaveInterval = TimeSpan.FromSeconds(5); saveTimer = new Timer(Save, null, (int)SaveInterval.TotalMilliseconds, Timeout.Infinite); tickTimer = new Timer(Tick, null, TickLength, TickLength); return; } LoadFromFile(directory); // Move spawn point var chunk = World.GetChunk(World.WorldToChunkCoordinates(SpawnPoint)); var relativeSpawn = World.FindBlockPosition(SpawnPoint); SpawnPoint = new Vector3(SpawnPoint.X, chunk.GetHeight((byte)relativeSpawn.X, (byte)relativeSpawn.Z), SpawnPoint.Z); SaveInterval = TimeSpan.FromSeconds(5); saveTimer = new Timer(Save, null, (int)SaveInterval.TotalMilliseconds, Timeout.Infinite); tickTimer = new Timer(Tick, null, TickLength, TickLength); }
/// <summary> /// Creates a new Region for server-side use at the given position using /// the provided terrain generator. /// </summary> public Region(Vector3 position, World world) { Chunks = new Dictionary<Vector3, Chunk>(); Position = position; World = world; WorldGenerator = world.WorldGenerator; }
internal ReadOnlyWorld() { World = new World(null); Level = new Level(World); World.EnableBlockUpdates = false; UnloadChunks = true; }
public void SpawnEntity(World world, Entity entity) { entity.Id = nextEntityId++; world.Entities.Add(entity); // Get nearby clients in the same world var clients = GetClientsInWorld(world) .Where(c => !c.IsDisconnected && c.Entity.Position.DistanceTo(entity.Position) < (c.ViewDistance * Chunk.Width)); entity.PropertyChanged += EntityOnPropertyChanged; if (clients.Count() != 0) { // Spawn entity on relevant clients if (entity is PlayerEntity) { // Isolate the client being spawned var client = clients.First(c => c.Entity == entity); client.Entity.BedStateChanged += EntityOnUpdateBedState; client.Entity.BedTimerExpired += EntityOnBedTimerExpired; clients = clients.Where(c => c.Entity != entity); clients.ToList().ForEach(c => { c.SendPacket(new SpawnNamedEntityPacket(client)); c.KnownEntities.Add(client.Entity.Id); }); } } server.ProcessSendQueue(); }
public override void OnItemUsedOnBlock(World world, Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, Entity usedBy) { var block = world.GetBlock(clickedBlock); var player = usedBy as PlayerEntity; var client = Server.EntityManager.GetClient(player); client.SendChat(block.GetType().Name + ": " + block.Id + " (" + block.Metadata + ")"); }
public WeatherManager(World world, MinecraftServer server) { Server = server; World = world; random = new Random(); ScheduleChange(true); ScheduleChange(false); }
public Level(World world) { World = world; Name = "world"; GameMode = GameMode.Survival; MapFeatures = false; Difficulty = Difficulty.Normal; }
public void SpawnEntity(World world, Entity entity) { entity.Id = nextEntityId++; world.Entities.Add(entity); // Get nearby clients in the same world var clients = GetClientsInWorld(world) .Where(c => c.Entity.Position.DistanceTo(entity.Position) < (c.ViewDistance * Chunk.Width)); entity.PropertyChanged += EntityOnPropertyChanged; if (entity is LivingEntity) (entity as LivingEntity).EntityDamaged += EntityDamaged; if (clients.Count() != 0) { // Spawn entity on relevant clients if (entity is PlayerEntity) { // Isolate the client being spawned (entity as PlayerEntity).Abilities.PropertyChanged += PlayerAbilitiesChanged; (entity as PlayerEntity).Inventory.WindowChange += PlayerInventoryChange; var client = clients.First(c => c.Entity == entity); client.Entity.BedStateChanged += EntityOnUpdateBedState; client.Entity.BedTimerExpired += EntityOnBedTimerExpired; client.Entity.StartEating += PlayerStartEating; client.Entity.PickUpItem += Entity_PickUpItem; clients = clients.Where(c => c.Entity != entity); clients.ToList().ForEach(c => { c.SendPacket(new SpawnPlayerPacket(client.Entity.Id, client.Username, MathHelper.CreateAbsoluteInt(client.Entity.Position.X), MathHelper.CreateAbsoluteInt(client.Entity.Position.Y), MathHelper.CreateAbsoluteInt(client.Entity.Position.Z), MathHelper.CreateRotationByte(client.Entity.Yaw), MathHelper.CreateRotationByte(client.Entity.Pitch), client.Entity.SelectedItem.Empty ? (short)0 : client.Entity.SelectedItem.Id, client.Entity.Metadata)); c.SendPacket(new EntityHeadLookPacket(client.Entity.Id, MathHelper.CreateRotationByte(client.Entity.Yaw))); for (int i = 0; i < 4; i++) { var item = client.Entity.Inventory[InventoryWindow.ArmorIndex + i]; if (!item.Empty) c.SendPacket(new EntityEquipmentPacket(client.Entity.Id, (EntityEquipmentPacket.EntityEquipmentSlot)(4 - i), item)); } c.KnownEntities.Add(client.Entity.Id); }); } else if (entity is ObjectEntity) { var objectEntity = entity as ObjectEntity; clients.ToList().ForEach(c => { c.SendPacket(new SpawnObjectPacket(objectEntity.Id, objectEntity.EntityType, MathHelper.CreateAbsoluteInt(objectEntity.Position.X), MathHelper.CreateAbsoluteInt(objectEntity.Position.Y), MathHelper.CreateAbsoluteInt(objectEntity.Position.Z), MathHelper.CreateRotationByte(objectEntity.Yaw), MathHelper.CreateRotationByte(objectEntity.Pitch), objectEntity.Data, (short)objectEntity.Velocity.X, (short)objectEntity.Velocity.Y, (short)objectEntity.Velocity.Z)); if (entity.IncludeMetadataOnClient) c.SendPacket(new EntityMetadataPacket(entity.Id, entity.Metadata)); c.KnownEntities.Add(entity.Id); }); } } }
public void SpawnEntity(World world, Entity entity) { entity.Id = nextEntityId++; world.Entities.Add(entity); // Get nearby clients in the same world var clients = GetClientsInWorld(world) .Where(c => !c.IsDisconnected && c.Entity.Position.DistanceTo(entity.Position) < (c.ViewDistance * Chunk.Width)); entity.PropertyChanged += EntityOnPropertyChanged; if (entity is LivingEntity) (entity as LivingEntity).EntityDamaged += EntityDamaged; if (clients.Count() != 0) { // Spawn entity on relevant clients if (entity is PlayerEntity) { // Isolate the client being spawned (entity as PlayerEntity).Abilities.PropertyChanged += PlayerAbilitiesChanged; (entity as PlayerEntity).Inventory.WindowChange += PlayerInventoryChange; var client = clients.First(c => c.Entity == entity); client.Entity.BedStateChanged += EntityOnUpdateBedState; client.Entity.BedTimerExpired += EntityOnBedTimerExpired; client.Entity.StartEating += PlayerStartEating; client.Entity.PickUpItem += Entity_PickUpItem; clients = clients.Where(c => c.Entity != entity); clients.ToList().ForEach(c => { c.SendPacket(new SpawnNamedEntityPacket(client)); c.SendPacket(new EntityHeadLookPacket(client.Entity)); for (int i = 0; i < 4; i++) { var item = client.Entity.Inventory[InventoryWindow.ArmorIndex + i]; if (!item.Empty) c.SendPacket(new EntityEquipmentPacket(client.Entity.Id, (EntityEquipmentSlot)(4 - i), item)); } c.KnownEntities.Add(client.Entity.Id); }); } else if (entity is ItemEntity) { clients.ToList().ForEach(c => { c.SendPacket(new SpawnDroppedItemPacket(entity as ItemEntity)); c.KnownEntities.Add(entity.Id); }); } else if (entity is ObjectEntity) { clients.ToList().ForEach(c => { c.SendPacket(new SpawnObjectPacket(entity as ObjectEntity)); c.KnownEntities.Add(entity.Id); }); } } server.ProcessSendQueue(); }
/// <summary> /// Creates a region from the given region file. /// </summary> public Region(Vector3 position, World world, string file) : this(position, world) { if (File.Exists(file)) regionFile = File.Open(file, FileMode.OpenOrCreate); else { regionFile = File.Open(file, FileMode.OpenOrCreate); CreateRegionHeader(); } }
/// <summary> /// Called when this item is used, even when a block is not targeted. /// </summary> public virtual void OnItemUsed(World world, Entity usedBy) { var player = usedBy as PlayerEntity; if (player != null && player.GameMode != GameMode.Creative) { var slot = player.Inventory[player.SelectedSlot]; player.Inventory[player.SelectedSlot] = new ItemStack(slot.Id, (sbyte)(slot.Count - 1), slot.Metadata, slot.Nbt); } }
public override void OnItemUsed(World world, Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, Entity usedBy) { var clicked = world.GetBlock(clickedBlock); if (clicked.OnBlockRightClicked(clickedBlock, clickedSide, cursorPosition, world, usedBy)) { if (OnBlockPlaced(world, clickedBlock + clickedSide, clickedBlock, clickedSide, cursorPosition, usedBy)) { if ((clickedBlock + clickedSide).Y >= 0 && (clickedBlock + clickedSide).Y <= Chunk.Height) world.SetBlock(clickedBlock + clickedSide, this); } } }
/// <summary> /// Default constructor for a level that only exists in memory. /// </summary> public Level() { World = new World(this, DefaultGenerator); Name = "world"; GameMode = GameMode.Survival; MapFeatures = false; WorldGenerator = DefaultGenerator; Seed = GenerateSeed(); WorldGenerator.Seed = Seed; WorldGenerator.Initialize(this); SpawnPoint = WorldGenerator.SpawnPoint; tickTimer = new Timer(Tick, null, TickLength, TickLength); Difficulty = Difficulty.Normal; }
/// <summary> /// Spawns a bolt of lightning in the given world /// at the given position. /// </summary> public void SpawnLightning(World world, Vector3 position) { var chunk = world.GetChunk(World.WorldToChunkCoordinates(position)); var block = World.FindBlockPosition(position); int y = chunk.GetHeight((byte)block.X, (byte)block.Z) + 1; var strike = new Vector3(position.X, y, position.Z); if (world.GetBlock(strike + Vector3.Down).Transparency == Transparency.Opaque) world.SetBlock(strike, new FireBlock()); var clients = Server.EntityManager.GetClientsInWorld(world); foreach (var minecraftClient in clients) minecraftClient.SendPacket(new SpawnGlobalEntityPacket(EntityManager.nextEntityId++, 1, (int)strike.X, (int)strike.Y, (int)strike.Z)); }
public override void OnItemUsedOnBlock(World world, Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, Entity usedBy) { var clicked = world.GetBlock(clickedBlock); var player = usedBy as PlayerEntity; if (player.GameMode != GameMode.Creative) { var item = player.Inventory[player.SelectedSlot]; player.Inventory[player.SelectedSlot] = new ItemStack(item.Id, (sbyte)(item.Count - 1), item.Metadata, item.Nbt); } if (clicked.OnBlockRightClicked(clickedBlock, clickedSide, cursorPosition, world, usedBy)) { if (OnBlockPlaced(world, clickedBlock + clickedSide, clickedBlock, clickedSide, cursorPosition, usedBy)) { if ((clickedBlock + clickedSide).Y >= 0 && (clickedBlock + clickedSide).Y <= Chunk.Height) world.SetBlock(clickedBlock + clickedSide, this); } } }
public void DespawnEntity(World world, Entity entity) { if (world == null) return; if (!world.Entities.Contains(entity)) return; entity.PropertyChanged -= EntityOnPropertyChanged; world.Entities.Remove(entity); var clients = GetClientsInWorld(world).Where(c => c.KnownEntities.Contains(entity.Id)); foreach (var client in clients) { client.KnownEntities.Remove(entity.Id); client.SendPacket(new DestroyEntityPacket(entity.Id)); } server.ProcessSendQueue(); }
/// <summary> /// Called when this item is used by a player. /// </summary> public virtual void OnItemUsedOnBlock(World world, Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, Entity usedBy) { // Run the default handler unless overriden OnItemUsed(world, usedBy); }
public Level GetLevel(World world) { return Levels.First(l => l.World == world); }
/// <summary> /// Spawns a bolt of lightning in the given world /// at the given position. /// </summary> public void SpawnLightning(World world, Vector3 position) { var chunk = world.GetChunk(World.WorldToChunkCoordinates(position)); var block = World.FindBlockPosition(position); byte y = (byte)(chunk.GetHeight((byte)block.X, (byte)block.Z) + 1); var strike = new Vector3(position.X, y, position.Z); if (world.GetBlock(strike + Vector3.Down).Transparency == Transparency.Opaque) world.SetBlock(strike, new FireBlock()); var clients = GetClientsInWorld(world); foreach (var minecraftClient in clients) minecraftClient.SendPacket(new SpawnLightningPacket(EntityManager.nextEntityId++, strike)); ProcessSendQueue(); }
/// <summary> /// Gets all <see cref="MinecraftClient"/> objects in the given /// world. /// </summary> public IEnumerable<MinecraftClient> GetClientsInWorld(World world) { return EntityManager.GetClientsInWorld(world); }
/// <summary> /// Called when an entity walks on top of the block. /// </summary> public virtual void OnBlockWalkedOn(World world, Vector3 position, Entity entity) { }
public WeatherManager(World world, MinecraftServer server) { Server = server; World = world; }
/// <summary> /// Called when this item is used, even when a block is not targeted. /// </summary> public virtual void OnItemUsed(World world, Entity usedBy) { var player = usedBy as PlayerEntity; if (player != null && player.GameMode != GameMode.Creative) player.Inventory[player.SelectedSlot].Count--; }
public WeatherManager GetWeatherManagerForWorld(World world) { return WeatherManagers.FirstOrDefault(w => w.World == world); }
/// <summary> /// When the block is placed, this will be called. Return /// false to cancel block placement. The default behavoir /// is to simply place the block. /// </summary> public virtual bool OnBlockPlaced(World world, Vector3 position, Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, Entity usedBy) { return true; }
/// <summary> /// Called when this item is used by a player. /// </summary> public virtual void OnItemUsed(World world, Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, Entity usedBy) { }
/// <summary> /// Called when an entity walks inside of the block. /// </summary> public virtual void OnBlockWalkedIn(World world, Vector3 position, Entity entity) { // TODO: Default handler to kick the entity out }
public IEnumerable<MinecraftClient> GetClientsInWorld(World world) { return server.Clients.Where(c => world.Entities.Contains(c.Entity)); }
public void DespawnEntity(World world, Entity entity) { if (world == null) return; if (!world.Entities.Contains(entity)) return; entity.PropertyChanged -= EntityOnPropertyChanged; world.Entities.Remove(entity); var clients = GetClientsInWorld(world).Where(c => c.KnownEntities.Contains(entity.Id)); foreach (var client in clients) { client.KnownEntities.Remove(entity.Id); client.SendPacket(new DestroyEntityPacket(new[] { entity.Id })); // TODO: Investigate handling this in bulk } }
/// <summary> /// When the block is clicked, this will be called. Return /// false to cancel block placement if relevant. /// </summary> public virtual bool OnBlockRightClicked(Vector3 clickedBlock, Vector3 clickedSide, Vector3 cursorPosition, World world, Entity usedBy) { return true; }