fix some issues with /gun

This commit is contained in:
UnknownShadow200 2019-02-01 10:19:42 +11:00
parent 70593dde6c
commit 4bf0b21023
7 changed files with 184 additions and 180 deletions

View File

@ -58,10 +58,7 @@ namespace MCGalaxy.Core {
foreach (Zone zn in zones) { zn.Show(p); } foreach (Zone zn in zones) { zn.Show(p); }
} }
if (p.aiming && !level.Config.Guns) { if (p.weapon != null && !level.Config.Guns) p.weapon.Disable();
p.aiming = false;
p.ClearBlockchange();
}
if (!level.Config.UseBlockDB) { if (!level.Config.UseBlockDB) {
p.Message("BlockDB is disabled here, %Wyou will not be able to /undo or /redo"); p.Message("BlockDB is disabled here, %Wyou will not be able to /undo or /redo");
} }

View File

@ -175,10 +175,10 @@ namespace MCGalaxy.Drawing.Ops {
if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block]) return; if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block]) return;
// Check if player can affect block at coords in world // Check if player can affect block at coords in world
AccessController denied = lvl.CanAffect(p, b.X, b.Y, b.Z); AccessController denier = lvl.CanAffect(p, b.X, b.Y, b.Z);
if (denied != null) { if (denier != null) {
if (p.lastAccessStatus < DateTime.UtcNow) { if (p.lastAccessStatus < DateTime.UtcNow) {
denied.CheckDetailed(p); denier.CheckDetailed(p);
p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2); p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2);
} }
return; return;

View File

@ -75,12 +75,9 @@ namespace MCGalaxy.Games {
void ResetPlayerFlag(Player p, CtfData data) { void ResetPlayerFlag(Player p, CtfData data) {
Vec3S32 last = data.LastHeadPos; Vec3S32 last = data.LastHeadPos;
ushort x = (ushort)last.X, y = (ushort)last.Y, z = (ushort)last.Z; ushort x = (ushort)last.X, y = (ushort)last.Y, z = (ushort)last.Z;
data.LastHeadPos = default(Vec3S32);
BlockID origBlock = Map.GetBlock(x, y, z); data.LastHeadPos = default(Vec3S32);
if (origBlock != Block.Invalid) { Map.BroadcastRevert(x, y, z);
Map.BroadcastChange(x, y, z, origBlock);
}
} }
void DrawPlayerFlag(Player p, CtfData data) { void DrawPlayerFlag(Player p, CtfData data) {

View File

@ -52,7 +52,7 @@ namespace MCGalaxy.Games {
if (args.iterations > 12) { if (args.iterations > 12) {
Vec3U16 pos = args.visible[0]; Vec3U16 pos = args.visible[0];
args.visible.RemoveAt(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; return true;
} }
@ -63,7 +63,7 @@ namespace MCGalaxy.Games {
if (args.visible.Count > 0) { if (args.visible.Count > 0) {
Vec3U16 pos = args.visible[0]; Vec3U16 pos = args.visible[0];
args.visible.RemoveAt(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; return args.visible.Count > 0;
} }
@ -88,7 +88,7 @@ namespace MCGalaxy.Games {
if (cur != Block.Air && !args.all.Contains(pos) && OnHitBlock(args, pos, cur)) if (cur != Block.Air && !args.all.Contains(pos) && OnHitBlock(args, pos, cur))
return false; 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.visible.Add(pos);
args.all.Add(pos); args.all.Add(pos);
@ -145,7 +145,7 @@ namespace MCGalaxy.Games {
args.all.Clear(); args.all.Clear();
} else { } else {
foreach (Vec3U16 pos in args.visible) { 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(); args.visible.Clear();
} }

View File

@ -25,171 +25,172 @@ using BlockID = System.UInt16;
namespace MCGalaxy.Games { namespace MCGalaxy.Games {
/// <summary> Represents a weapon which can interact with blocks or players until it dies. </summary> /// <summary> Represents a weapon which can interact with blocks or players until it dies. </summary>
/// <remarks> Activated by clicking through either PlayerClick or a glass box around the player. </remarks> /// <remarks> Activated by clicking through either PlayerClick or a glass box around the player. </remarks>
public abstract class Weapon { public abstract class Weapon {
public abstract string Name { get; } public abstract string Name { get; }
static bool hookedEvents; static bool hookedEvents;
protected Player p; protected Player p;
AimBox aimer; AimBox aimer;
public void Enable(Player p) { public void Enable(Player p) {
if (!hookedEvents) { if (!hookedEvents) {
OnPlayerClickEvent.Register(PlayerClickCallback, Priority.Low); OnPlayerClickEvent.Register(PlayerClickCallback, Priority.Low);
hookedEvents = true; hookedEvents = true;
} }
this.p = p; this.p = p;
p.ClearBlockchange(); p.ClearBlockchange();
if (p.Supports(CpeExt.PlayerClick)) { if (p.Supports(CpeExt.PlayerClick)) {
p.Message(Name + " engaged, click to fire at will"); p.Message(Name + " engaged, click to fire at will");
} else { } else {
p.Blockchange += BlockClickCallback; p.Blockchange += BlockClickCallback;
p.Message(Name + " engaged, fire at will"); p.Message(Name + " engaged, fire at will");
aimer = new AimBox(); aimer = new AimBox();
aimer.Hook(p); aimer.Hook(p);
} }
} }
public void Disable() { public void Disable() {
p.aiming = false; p.aiming = false;
p.ClearBlockchange(); p.ClearBlockchange();
p.Message(Name + " disabled"); p.Message(Name + " disabled");
} p.weapon = null;
}
protected abstract void OnActivated(byte yaw, byte pitch, BlockID block);
protected abstract void OnActivated(byte yaw, byte pitch, BlockID block);
static void BlockClickCallback(Player p, ushort x, ushort y, ushort z, BlockID block) { static void BlockClickCallback(Player p, ushort x, ushort y, ushort z, BlockID block) {
Weapon weapon = p.weapon; Weapon weapon = p.weapon;
if (weapon == null) return; if (weapon == null) return;
p.RevertBlock(x, y, z); p.RevertBlock(x, y, z);
// defer to player click handler // defer to player click handler
if (weapon.aimer == null) return; if (weapon.aimer == null) return;
if (!p.level.Config.Guns) { weapon.Disable(); return; } if (!p.level.Config.Guns) { weapon.Disable(); return; }
if (!CommandParser.IsBlockAllowed(p, "use", block)) return; if (!CommandParser.IsBlockAllowed(p, "use", block)) return;
weapon.OnActivated(p.Rot.RotY, p.Rot.HeadX, block); weapon.OnActivated(p.Rot.RotY, p.Rot.HeadX, block);
} }
static void PlayerClickCallback(Player p, MouseButton btn, MouseAction action, static void PlayerClickCallback(Player p, MouseButton btn, MouseAction action,
ushort yaw, ushort pitch, byte entity, ushort yaw, ushort pitch, byte entity,
ushort x, ushort y, ushort z, TargetBlockFace face) { ushort x, ushort y, ushort z, TargetBlockFace face) {
Weapon weapon = p.weapon; Weapon weapon = p.weapon;
if (weapon == null || action != MouseAction.Pressed) return; if (weapon == null || action != MouseAction.Pressed) return;
if (!(btn == MouseButton.Left || btn == MouseButton.Right)) return; if (!(btn == MouseButton.Left || btn == MouseButton.Right)) return;
if (!p.level.Config.Guns) { weapon.Disable(); return; } if (!p.level.Config.Guns) { weapon.Disable(); return; }
BlockID held = p.RawHeldBlock; BlockID held = p.RawHeldBlock;
if (!CommandParser.IsBlockAllowed(p, "use", held)) return; if (!CommandParser.IsBlockAllowed(p, "use", held)) return;
weapon.OnActivated((byte)(yaw >> 8), (byte)(pitch >> 8), held); weapon.OnActivated((byte)(yaw >> 8), (byte)(pitch >> 8), held);
} }
protected static Player PlayerAt(Player p, Vec3U16 pos, bool skipSelf) { protected static Player PlayerAt(Player p, Vec3U16 pos, bool skipSelf) {
Player[] players = PlayerInfo.Online.Items; Player[] players = PlayerInfo.Online.Items;
foreach (Player pl in players) { foreach (Player pl in players) {
if (pl.level != p.level) continue; if (pl.level != p.level) continue;
if (p == pl && skipSelf) continue; if (p == pl && skipSelf) continue;
if (Math.Abs(pl.Pos.BlockX - pos.X) <= 1 if (Math.Abs(pl.Pos.BlockX - pos.X) <= 1
&& Math.Abs(pl.Pos.BlockY - pos.Y) <= 1 && Math.Abs(pl.Pos.BlockY - pos.Y) <= 1
&& Math.Abs(pl.Pos.BlockZ - pos.Z) <= 1) && Math.Abs(pl.Pos.BlockZ - pos.Z) <= 1)
{ {
return pl; return pl;
} }
} }
return null; return null;
} }
} }
public class AmmunitionData { public class AmmunitionData {
public BlockID block; public BlockID block;
public Vec3U16 pos, start; public Vec3U16 pos, start;
public Vec3F32 dir; public Vec3F32 dir;
public bool moving = true; public bool moving = true;
// positions of all currently visible "trailing" blocks // positions of all currently visible "trailing" blocks
public List<Vec3U16> visible = new List<Vec3U16>(); public List<Vec3U16> visible = new List<Vec3U16>();
// position of all blocks this ammunition has touched/gone through // position of all blocks this ammunition has touched/gone through
public List<Vec3U16> all = new List<Vec3U16>(); public List<Vec3U16> all = new List<Vec3U16>();
public int iterations; public int iterations;
public Vec3U16 PosAt(int i) { public Vec3U16 PosAt(int i) {
Vec3U16 target; Vec3U16 target;
target.X = (ushort)Math.Round(start.X + (double)(dir.X * i)); target.X = (ushort)Math.Round(start.X + (double)(dir.X * i));
target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i)); target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i));
target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i)); target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i));
return target; return target;
} }
} }
/// <summary> Manages the glass box around the player. Adjusts based on where player is looking. </summary> /// <summary> Manages the glass box around the player. Adjusts based on where player is looking. </summary>
internal sealed class AimBox { internal sealed class AimBox {
Player player; Player player;
List<Vec3U16> lastGlass = new List<Vec3U16>(); List<Vec3U16> lastGlass = new List<Vec3U16>();
List<Vec3U16> curGlass = new List<Vec3U16>(); List<Vec3U16> curGlass = new List<Vec3U16>();
public void Hook(Player p) { public void Hook(Player p) {
player = p; player = p;
SchedulerTask task = new SchedulerTask(AimCallback, null, TimeSpan.Zero, true); SchedulerTask task = new SchedulerTask(AimCallback, null, TimeSpan.Zero, true);
p.CriticalTasks.Add(task); p.CriticalTasks.Add(task);
} }
void AimCallback(SchedulerTask task) { void AimCallback(SchedulerTask task) {
Player p = player; Player p = player;
if (p.aiming) { Update(); return; } if (p.aiming) { Update(); return; }
foreach (Vec3U16 pos in lastGlass) { foreach (Vec3U16 pos in lastGlass) {
if (!p.level.IsValidPos(pos)) continue; if (!p.level.IsValidPos(pos)) continue;
p.RevertBlock(pos.X, pos.Y, pos.Z); p.RevertBlock(pos.X, pos.Y, pos.Z);
} }
task.Repeating = false; task.Repeating = false;
} }
void Update() { void Update() {
Player p = player; Player p = player;
Vec3F32 dir = DirUtils.GetDirVector(p.Rot.RotY, p.Rot.HeadX); Vec3F32 dir = DirUtils.GetDirVector(p.Rot.RotY, p.Rot.HeadX);
ushort x = (ushort)Math.Round(p.Pos.BlockX + dir.X * 3); ushort x = (ushort)Math.Round(p.Pos.BlockX + dir.X * 3);
ushort y = (ushort)Math.Round(p.Pos.BlockY + dir.Y * 3); ushort y = (ushort)Math.Round(p.Pos.BlockY + dir.Y * 3);
ushort z = (ushort)Math.Round(p.Pos.BlockZ + dir.Z * 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; 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, y, z );
Check(p.level, x + dx, y, z ); Check(p.level, x + dx, y, z );
Check(p.level, x, y, z + dz); Check(p.level, x, y, z + dz);
Check(p.level, x + dx, 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 // Revert all glass blocks now not in the ray from the player's direction
for (int i = 0; i < lastGlass.Count; i++) { for (int i = 0; i < lastGlass.Count; i++) {
Vec3U16 pos = lastGlass[i]; Vec3U16 pos = lastGlass[i];
if (curGlass.Contains(pos)) continue; if (curGlass.Contains(pos)) continue;
if (p.level.IsValidPos(pos)) if (p.level.IsValidPos(pos))
p.RevertBlock(pos.X, pos.Y, pos.Z); p.RevertBlock(pos.X, pos.Y, pos.Z);
lastGlass.RemoveAt(i); i--; lastGlass.RemoveAt(i); i--;
} }
// Place the new glass blocks that are in the ray from the player's direction // Place the new glass blocks that are in the ray from the player's direction
foreach (Vec3U16 pos in curGlass) { foreach (Vec3U16 pos in curGlass) {
if (lastGlass.Contains(pos)) continue; if (lastGlass.Contains(pos)) continue;
lastGlass.Add(pos); lastGlass.Add(pos);
p.SendBlockchange(pos.X, pos.Y, pos.Z, Block.Glass); p.SendBlockchange(pos.X, pos.Y, pos.Z, Block.Glass);
} }
curGlass.Clear(); curGlass.Clear();
} }
void Check(Level lvl, int x, int y, int z) { void Check(Level lvl, int x, int y, int z) {
Vec3U16 pos = new Vec3U16((ushort)x, (ushort)(y - 1), (ushort)z); Vec3U16 pos = new Vec3U16((ushort)x, (ushort)(y - 1), (ushort)z);
if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos); if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
pos.Y++; pos.Y++;
if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos); if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
} }
} }
} }

View File

@ -35,7 +35,7 @@ namespace MCGalaxy.Generator.Foliage {
public virtual int MinSize { get { return 3; } } public virtual int MinSize { get { return 3; } }
/// <summary> Maximum allowed size (usually means height) for this tree. </summary> /// <summary> Maximum allowed size (usually means height) for this tree. </summary>
public virtual int MaxSize { get { return 100; } } public virtual int MaxSize { get { return 4096; } }
/// <summary> Estimated the maximum number of blocks affected by this tree. </summary> /// <summary> Estimated the maximum number of blocks affected by this tree. </summary>
public abstract int EstimateBlocksAffected(); public abstract int EstimateBlocksAffected();

View File

@ -180,6 +180,8 @@ namespace MCGalaxy {
return block >= Block.Water && block <= Block.StillLava; return block >= Block.Water && block <= Block.StillLava;
} }
/// <summary> Returns the AccessController denying the player from changing blocks at the given coordinates. </summary>
/// <remarks> If no AccessController denies the player, returns null. </remarks>
public AccessController CanAffect(Player p, ushort x, ushort y, ushort z) { public AccessController CanAffect(Player p, ushort x, ushort y, ushort z) {
Zone[] zones = Zones.Items; Zone[] zones = Zones.Items;
if (zones.Length == 0) goto checkRank; // TODO: avoid this 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) { 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; if (!p.group.Blocks[old] || !p.group.Blocks[block]) return false;
AccessController denied = CanAffect(p, x, y, z); AccessController denier = CanAffect(p, x, y, z);
if (denied == null) return true; if (denier == null) return true;
if (p.lastAccessStatus < DateTime.UtcNow) { if (p.lastAccessStatus < DateTime.UtcNow) {
denied.CheckDetailed(p); denier.CheckDetailed(p);
p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2); p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2);
} }
return false; return false;
@ -234,6 +236,13 @@ namespace MCGalaxy {
} }
} }
/// <summary> Sends a block update packet to all players in this level. </summary>
/// <remarks> The block sent is the current block at the given coordinates. </remarks>
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) { 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); if (DoBlockchange(p, x, y, z, block) == 2) BroadcastChange(x, y, z, block);