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); }
}
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");
}

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}

View File

@ -25,171 +25,172 @@ using BlockID = System.UInt16;
namespace MCGalaxy.Games {
/// <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>
public abstract class Weapon {
/// <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>
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<Vec3U16> visible = new List<Vec3U16>();
// position of all blocks this ammunition has touched/gone through
public List<Vec3U16> all = new List<Vec3U16>();
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;
}
}
/// <summary> Manages the glass box around the player. Adjusts based on where player is looking. </summary>
internal sealed class AimBox {
Player player;
List<Vec3U16> lastGlass = new List<Vec3U16>();
List<Vec3U16> curGlass = new List<Vec3U16>();
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<Vec3U16> visible = new List<Vec3U16>();
// position of all blocks this ammunition has touched/gone through
public List<Vec3U16> all = new List<Vec3U16>();
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;
}
}
/// <summary> Manages the glass box around the player. Adjusts based on where player is looking. </summary>
internal sealed class AimBox {
Player player;
List<Vec3U16> lastGlass = new List<Vec3U16>();
List<Vec3U16> curGlass = new List<Vec3U16>();
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);
}
}
}

View File

@ -35,7 +35,7 @@ namespace MCGalaxy.Generator.Foliage {
public virtual int MinSize { get { return 3; } }
/// <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>
public abstract int EstimateBlocksAffected();

View File

@ -180,6 +180,8 @@ namespace MCGalaxy {
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) {
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 {
}
}
/// <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) {
if (DoBlockchange(p, x, y, z, block) == 2) BroadcastChange(x, y, z, block);