diff --git a/MCGalaxy/CorePlugin/MiscHandlers.cs b/MCGalaxy/CorePlugin/MiscHandlers.cs
index 6c3111032..2af486cf4 100644
--- a/MCGalaxy/CorePlugin/MiscHandlers.cs
+++ b/MCGalaxy/CorePlugin/MiscHandlers.cs
@@ -58,10 +58,7 @@ namespace MCGalaxy.Core {
foreach (Zone zn in zones) { zn.Show(p); }
}
- if (p.aiming && !level.Config.Guns) {
- p.aiming = false;
- p.ClearBlockchange();
- }
+ if (p.weapon != null && !level.Config.Guns) p.weapon.Disable();
if (!level.Config.UseBlockDB) {
p.Message("BlockDB is disabled here, %Wyou will not be able to /undo or /redo");
}
diff --git a/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs b/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs
index 2530afa05..75257f85c 100644
--- a/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs
+++ b/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs
@@ -175,10 +175,10 @@ namespace MCGalaxy.Drawing.Ops {
if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block]) return;
// Check if player can affect block at coords in world
- AccessController denied = lvl.CanAffect(p, b.X, b.Y, b.Z);
- if (denied != null) {
+ AccessController denier = lvl.CanAffect(p, b.X, b.Y, b.Z);
+ if (denier != null) {
if (p.lastAccessStatus < DateTime.UtcNow) {
- denied.CheckDetailed(p);
+ denier.CheckDetailed(p);
p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2);
}
return;
diff --git a/MCGalaxy/Games/CTF/CtfGame.Round.cs b/MCGalaxy/Games/CTF/CtfGame.Round.cs
index 60ca94c1d..762e05666 100644
--- a/MCGalaxy/Games/CTF/CtfGame.Round.cs
+++ b/MCGalaxy/Games/CTF/CtfGame.Round.cs
@@ -75,12 +75,9 @@ namespace MCGalaxy.Games {
void ResetPlayerFlag(Player p, CtfData data) {
Vec3S32 last = data.LastHeadPos;
ushort x = (ushort)last.X, y = (ushort)last.Y, z = (ushort)last.Z;
- data.LastHeadPos = default(Vec3S32);
- BlockID origBlock = Map.GetBlock(x, y, z);
- if (origBlock != Block.Invalid) {
- Map.BroadcastChange(x, y, z, origBlock);
- }
+ data.LastHeadPos = default(Vec3S32);
+ Map.BroadcastRevert(x, y, z);
}
void DrawPlayerFlag(Player p, CtfData data) {
diff --git a/MCGalaxy/Games/Weapons/Guns.cs b/MCGalaxy/Games/Weapons/Guns.cs
index f5fc5c460..6176e52e9 100644
--- a/MCGalaxy/Games/Weapons/Guns.cs
+++ b/MCGalaxy/Games/Weapons/Guns.cs
@@ -52,7 +52,7 @@ namespace MCGalaxy.Games {
if (args.iterations > 12) {
Vec3U16 pos = args.visible[0];
args.visible.RemoveAt(0);
- p.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
+ p.level.BroadcastRevert(pos.X, pos.Y, pos.Z);
}
return true;
}
@@ -63,7 +63,7 @@ namespace MCGalaxy.Games {
if (args.visible.Count > 0) {
Vec3U16 pos = args.visible[0];
args.visible.RemoveAt(0);
- p.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
+ p.level.BroadcastRevert(pos.X, pos.Y, pos.Z);
}
return args.visible.Count > 0;
}
@@ -88,7 +88,7 @@ namespace MCGalaxy.Games {
if (cur != Block.Air && !args.all.Contains(pos) && OnHitBlock(args, pos, cur))
return false;
- p.level.Blockchange(pos.X, pos.Y, pos.Z, args.block);
+ p.level.BroadcastChange(pos.X, pos.Y, pos.Z, args.block);
args.visible.Add(pos);
args.all.Add(pos);
@@ -145,7 +145,7 @@ namespace MCGalaxy.Games {
args.all.Clear();
} else {
foreach (Vec3U16 pos in args.visible) {
- p.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
+ p.level.BroadcastRevert(pos.X, pos.Y, pos.Z);
}
args.visible.Clear();
}
diff --git a/MCGalaxy/Games/Weapons/Weapon.cs b/MCGalaxy/Games/Weapons/Weapon.cs
index a95b6bbb1..857121693 100644
--- a/MCGalaxy/Games/Weapons/Weapon.cs
+++ b/MCGalaxy/Games/Weapons/Weapon.cs
@@ -25,171 +25,172 @@ using BlockID = System.UInt16;
namespace MCGalaxy.Games {
- /// Represents a weapon which can interact with blocks or players until it dies.
- /// Activated by clicking through either PlayerClick or a glass box around the player.
- public abstract class Weapon {
+ /// Represents a weapon which can interact with blocks or players until it dies.
+ /// Activated by clicking through either PlayerClick or a glass box around the player.
+ public abstract class Weapon {
- public abstract string Name { get; }
- static bool hookedEvents;
-
- protected Player p;
- AimBox aimer;
-
- public void Enable(Player p) {
- if (!hookedEvents) {
- OnPlayerClickEvent.Register(PlayerClickCallback, Priority.Low);
- hookedEvents = true;
- }
- this.p = p;
- p.ClearBlockchange();
-
- if (p.Supports(CpeExt.PlayerClick)) {
- p.Message(Name + " engaged, click to fire at will");
- } else {
- p.Blockchange += BlockClickCallback;
- p.Message(Name + " engaged, fire at will");
- aimer = new AimBox();
- aimer.Hook(p);
- }
- }
+ public abstract string Name { get; }
+ static bool hookedEvents;
+
+ protected Player p;
+ AimBox aimer;
+
+ public void Enable(Player p) {
+ if (!hookedEvents) {
+ OnPlayerClickEvent.Register(PlayerClickCallback, Priority.Low);
+ hookedEvents = true;
+ }
+ this.p = p;
+ p.ClearBlockchange();
+
+ if (p.Supports(CpeExt.PlayerClick)) {
+ p.Message(Name + " engaged, click to fire at will");
+ } else {
+ p.Blockchange += BlockClickCallback;
+ p.Message(Name + " engaged, fire at will");
+ aimer = new AimBox();
+ aimer.Hook(p);
+ }
+ }
- public void Disable() {
- p.aiming = false;
- p.ClearBlockchange();
- p.Message(Name + " disabled");
- }
-
- protected abstract void OnActivated(byte yaw, byte pitch, BlockID block);
+ public void Disable() {
+ p.aiming = false;
+ p.ClearBlockchange();
+ p.Message(Name + " disabled");
+ p.weapon = null;
+ }
+
+ protected abstract void OnActivated(byte yaw, byte pitch, BlockID block);
-
- static void BlockClickCallback(Player p, ushort x, ushort y, ushort z, BlockID block) {
- Weapon weapon = p.weapon;
- if (weapon == null) return;
-
- p.RevertBlock(x, y, z);
- // defer to player click handler
- if (weapon.aimer == null) return;
-
- if (!p.level.Config.Guns) { weapon.Disable(); return; }
- if (!CommandParser.IsBlockAllowed(p, "use", block)) return;
+
+ static void BlockClickCallback(Player p, ushort x, ushort y, ushort z, BlockID block) {
+ Weapon weapon = p.weapon;
+ if (weapon == null) return;
+
+ p.RevertBlock(x, y, z);
+ // defer to player click handler
+ if (weapon.aimer == null) return;
+
+ if (!p.level.Config.Guns) { weapon.Disable(); return; }
+ if (!CommandParser.IsBlockAllowed(p, "use", block)) return;
- weapon.OnActivated(p.Rot.RotY, p.Rot.HeadX, block);
- }
-
- static void PlayerClickCallback(Player p, MouseButton btn, MouseAction action,
- ushort yaw, ushort pitch, byte entity,
- ushort x, ushort y, ushort z, TargetBlockFace face) {
- Weapon weapon = p.weapon;
- if (weapon == null || action != MouseAction.Pressed) return;
-
- if (!(btn == MouseButton.Left || btn == MouseButton.Right)) return;
- if (!p.level.Config.Guns) { weapon.Disable(); return; }
-
- BlockID held = p.RawHeldBlock;
- if (!CommandParser.IsBlockAllowed(p, "use", held)) return;
- weapon.OnActivated((byte)(yaw >> 8), (byte)(pitch >> 8), held);
- }
-
- protected static Player PlayerAt(Player p, Vec3U16 pos, bool skipSelf) {
- Player[] players = PlayerInfo.Online.Items;
- foreach (Player pl in players) {
- if (pl.level != p.level) continue;
- if (p == pl && skipSelf) continue;
-
- if (Math.Abs(pl.Pos.BlockX - pos.X) <= 1
- && Math.Abs(pl.Pos.BlockY - pos.Y) <= 1
- && Math.Abs(pl.Pos.BlockZ - pos.Z) <= 1)
- {
- return pl;
- }
- }
- return null;
- }
- }
-
- public class AmmunitionData {
- public BlockID block;
- public Vec3U16 pos, start;
- public Vec3F32 dir;
- public bool moving = true;
-
- // positions of all currently visible "trailing" blocks
- public List visible = new List();
- // position of all blocks this ammunition has touched/gone through
- public List all = new List();
- public int iterations;
-
- public Vec3U16 PosAt(int i) {
- Vec3U16 target;
- target.X = (ushort)Math.Round(start.X + (double)(dir.X * i));
- target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i));
- target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i));
- return target;
- }
- }
-
- /// Manages the glass box around the player. Adjusts based on where player is looking.
- internal sealed class AimBox {
-
- Player player;
- List lastGlass = new List();
- List curGlass = new List();
-
- public void Hook(Player p) {
- player = p;
- SchedulerTask task = new SchedulerTask(AimCallback, null, TimeSpan.Zero, true);
- p.CriticalTasks.Add(task);
- }
-
- void AimCallback(SchedulerTask task) {
- Player p = player;
- if (p.aiming) { Update(); return; }
-
- foreach (Vec3U16 pos in lastGlass) {
- if (!p.level.IsValidPos(pos)) continue;
- p.RevertBlock(pos.X, pos.Y, pos.Z);
- }
- task.Repeating = false;
- }
-
- void Update() {
- Player p = player;
- Vec3F32 dir = DirUtils.GetDirVector(p.Rot.RotY, p.Rot.HeadX);
- ushort x = (ushort)Math.Round(p.Pos.BlockX + dir.X * 3);
- ushort y = (ushort)Math.Round(p.Pos.BlockY + dir.Y * 3);
- ushort z = (ushort)Math.Round(p.Pos.BlockZ + dir.Z * 3);
+ weapon.OnActivated(p.Rot.RotY, p.Rot.HeadX, block);
+ }
+
+ static void PlayerClickCallback(Player p, MouseButton btn, MouseAction action,
+ ushort yaw, ushort pitch, byte entity,
+ ushort x, ushort y, ushort z, TargetBlockFace face) {
+ Weapon weapon = p.weapon;
+ if (weapon == null || action != MouseAction.Pressed) return;
+
+ if (!(btn == MouseButton.Left || btn == MouseButton.Right)) return;
+ if (!p.level.Config.Guns) { weapon.Disable(); return; }
+
+ BlockID held = p.RawHeldBlock;
+ if (!CommandParser.IsBlockAllowed(p, "use", held)) return;
+ weapon.OnActivated((byte)(yaw >> 8), (byte)(pitch >> 8), held);
+ }
+
+ protected static Player PlayerAt(Player p, Vec3U16 pos, bool skipSelf) {
+ Player[] players = PlayerInfo.Online.Items;
+ foreach (Player pl in players) {
+ if (pl.level != p.level) continue;
+ if (p == pl && skipSelf) continue;
+
+ if (Math.Abs(pl.Pos.BlockX - pos.X) <= 1
+ && Math.Abs(pl.Pos.BlockY - pos.Y) <= 1
+ && Math.Abs(pl.Pos.BlockZ - pos.Z) <= 1)
+ {
+ return pl;
+ }
+ }
+ return null;
+ }
+ }
+
+ public class AmmunitionData {
+ public BlockID block;
+ public Vec3U16 pos, start;
+ public Vec3F32 dir;
+ public bool moving = true;
+
+ // positions of all currently visible "trailing" blocks
+ public List visible = new List();
+ // position of all blocks this ammunition has touched/gone through
+ public List all = new List();
+ public int iterations;
+
+ public Vec3U16 PosAt(int i) {
+ Vec3U16 target;
+ target.X = (ushort)Math.Round(start.X + (double)(dir.X * i));
+ target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i));
+ target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i));
+ return target;
+ }
+ }
+
+ /// Manages the glass box around the player. Adjusts based on where player is looking.
+ internal sealed class AimBox {
+
+ Player player;
+ List lastGlass = new List();
+ List curGlass = new List();
+
+ public void Hook(Player p) {
+ player = p;
+ SchedulerTask task = new SchedulerTask(AimCallback, null, TimeSpan.Zero, true);
+ p.CriticalTasks.Add(task);
+ }
+
+ void AimCallback(SchedulerTask task) {
+ Player p = player;
+ if (p.aiming) { Update(); return; }
+
+ foreach (Vec3U16 pos in lastGlass) {
+ if (!p.level.IsValidPos(pos)) continue;
+ p.RevertBlock(pos.X, pos.Y, pos.Z);
+ }
+ task.Repeating = false;
+ }
+
+ void Update() {
+ Player p = player;
+ Vec3F32 dir = DirUtils.GetDirVector(p.Rot.RotY, p.Rot.HeadX);
+ ushort x = (ushort)Math.Round(p.Pos.BlockX + dir.X * 3);
+ ushort y = (ushort)Math.Round(p.Pos.BlockY + dir.Y * 3);
+ ushort z = (ushort)Math.Round(p.Pos.BlockZ + dir.Z * 3);
- int dx = Math.Sign(dir.X) >= 0 ? 1 : -1, dz = Math.Sign(dir.Z) >= 0 ? 1 : -1;
- Check(p.level, x, y, z );
- Check(p.level, x + dx, y, z );
- Check(p.level, x, y, z + dz);
- Check(p.level, x + dx, y, z + dz);
+ int dx = Math.Sign(dir.X) >= 0 ? 1 : -1, dz = Math.Sign(dir.Z) >= 0 ? 1 : -1;
+ Check(p.level, x, y, z );
+ Check(p.level, x + dx, y, z );
+ Check(p.level, x, y, z + dz);
+ Check(p.level, x + dx, y, z + dz);
- // Revert all glass blocks now not in the ray from the player's direction
- for (int i = 0; i < lastGlass.Count; i++) {
- Vec3U16 pos = lastGlass[i];
- if (curGlass.Contains(pos)) continue;
-
- if (p.level.IsValidPos(pos))
- p.RevertBlock(pos.X, pos.Y, pos.Z);
- lastGlass.RemoveAt(i); i--;
- }
+ // Revert all glass blocks now not in the ray from the player's direction
+ for (int i = 0; i < lastGlass.Count; i++) {
+ Vec3U16 pos = lastGlass[i];
+ if (curGlass.Contains(pos)) continue;
+
+ if (p.level.IsValidPos(pos))
+ p.RevertBlock(pos.X, pos.Y, pos.Z);
+ lastGlass.RemoveAt(i); i--;
+ }
- // Place the new glass blocks that are in the ray from the player's direction
- foreach (Vec3U16 pos in curGlass) {
- if (lastGlass.Contains(pos)) continue;
- lastGlass.Add(pos);
- p.SendBlockchange(pos.X, pos.Y, pos.Z, Block.Glass);
- }
- curGlass.Clear();
- }
-
- void Check(Level lvl, int x, int y, int z) {
- Vec3U16 pos = new Vec3U16((ushort)x, (ushort)(y - 1), (ushort)z);
- if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
-
- pos.Y++;
- if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
- }
- }
+ // Place the new glass blocks that are in the ray from the player's direction
+ foreach (Vec3U16 pos in curGlass) {
+ if (lastGlass.Contains(pos)) continue;
+ lastGlass.Add(pos);
+ p.SendBlockchange(pos.X, pos.Y, pos.Z, Block.Glass);
+ }
+ curGlass.Clear();
+ }
+
+ void Check(Level lvl, int x, int y, int z) {
+ Vec3U16 pos = new Vec3U16((ushort)x, (ushort)(y - 1), (ushort)z);
+ if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
+
+ pos.Y++;
+ if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
+ }
+ }
}
diff --git a/MCGalaxy/Generator/Foliage/Tree.cs b/MCGalaxy/Generator/Foliage/Tree.cs
index bedb1bf20..da433ba71 100644
--- a/MCGalaxy/Generator/Foliage/Tree.cs
+++ b/MCGalaxy/Generator/Foliage/Tree.cs
@@ -35,7 +35,7 @@ namespace MCGalaxy.Generator.Foliage {
public virtual int MinSize { get { return 3; } }
/// Maximum allowed size (usually means height) for this tree.
- public virtual int MaxSize { get { return 100; } }
+ public virtual int MaxSize { get { return 4096; } }
/// Estimated the maximum number of blocks affected by this tree.
public abstract int EstimateBlocksAffected();
diff --git a/MCGalaxy/Levels/Level.Blocks.cs b/MCGalaxy/Levels/Level.Blocks.cs
index 2f6d8696c..05e06ac25 100644
--- a/MCGalaxy/Levels/Level.Blocks.cs
+++ b/MCGalaxy/Levels/Level.Blocks.cs
@@ -180,6 +180,8 @@ namespace MCGalaxy {
return block >= Block.Water && block <= Block.StillLava;
}
+ /// Returns the AccessController denying the player from changing blocks at the given coordinates.
+ /// If no AccessController denies the player, returns null.
public AccessController CanAffect(Player p, ushort x, ushort y, ushort z) {
Zone[] zones = Zones.Items;
if (zones.Length == 0) goto checkRank; // TODO: avoid this
@@ -216,11 +218,11 @@ namespace MCGalaxy {
public bool CheckAffect(Player p, ushort x, ushort y, ushort z, BlockID old, BlockID block) {
if (!p.group.Blocks[old] || !p.group.Blocks[block]) return false;
- AccessController denied = CanAffect(p, x, y, z);
- if (denied == null) return true;
+ AccessController denier = CanAffect(p, x, y, z);
+ if (denier == null) return true;
if (p.lastAccessStatus < DateTime.UtcNow) {
- denied.CheckDetailed(p);
+ denier.CheckDetailed(p);
p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2);
}
return false;
@@ -234,6 +236,13 @@ namespace MCGalaxy {
}
}
+ /// Sends a block update packet to all players in this level.
+ /// The block sent is the current block at the given coordinates.
+ public void BroadcastRevert(ushort x, ushort y, ushort z) {
+ BlockID block = GetBlock(x, y, z);
+ if (block != Block.Invalid) BroadcastChange(x, y, z, block);
+ }
+
public void Blockchange(Player p, ushort x, ushort y, ushort z, BlockID block) {
if (DoBlockchange(p, x, y, z, block) == 2) BroadcastChange(x, y, z, block);