Merge pull request #77 in MIN/mineplex from foo to master
* commit 'd7497ec09881047d7461630fac2c3b51bf37a06c': (23 commits) Fixed Micro Battle icon not appearing in stats menu Gravity's icon changed to ENDER_PORTAL_FRAME world's smallest bugfix - admin->co-host Fixed advertisement being able to be bypassed by spec and instant join fixed naming pets non-alphanumeric characters changed reference to premium ranks removed important debug thing fixed ssm enderman always facing south on teleport fixed bacon blast exloding blocks fixed shield smash and fissure affecting spectators fixed slab issue with Assassin's Flash Re-fixed Barbarian bug Fixed SG Barbarian bug SSM bug fix: magma cube flame dash doesn't make player invisible fixed several smash bugs and one global issue Slightly bumped Monster Maze jump time value fixed bridge bug "Death Bomber counts suicides as well" typo fix in legendary aura description Update achievement kit reference text Fixed tnt bug (SG) ...
This commit is contained in:
commit
c470ad880d
@ -105,7 +105,7 @@ public enum AchievementCategory
|
||||
|
||||
ONE_IN_THE_QUIVER("One in the Quiver", null,
|
||||
new StatDisplay[] { StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.KILLS, StatDisplay.DEATHS, StatDisplay.GEMS_EARNED },
|
||||
Material.BOW, 0, GameCategory.ARCADE, "Slam Shooter Kit"),
|
||||
Material.BOW, 0, GameCategory.ARCADE, "Ninja Kit"),
|
||||
|
||||
SUPER_PAINTBALL("Super Paintball", null,
|
||||
new StatDisplay[] { StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.KILLS, StatDisplay.DEATHS, StatDisplay.GEMS_EARNED },
|
||||
@ -137,7 +137,7 @@ public enum AchievementCategory
|
||||
|
||||
MICRO_BATTLE("Micro Battle", null,
|
||||
new StatDisplay[] { StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.KILLS, StatDisplay.DEATHS, StatDisplay.GEMS_EARNED },
|
||||
Material.LAVA, 0, GameCategory.ARCADE, null),
|
||||
Material.LAVA_BUCKET, 0, GameCategory.ARCADE, null),
|
||||
|
||||
BOMB_LOBBERS("Bomb Lobbers", null,
|
||||
new StatDisplay[] { StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.KILLS, StatDisplay.DEATHS, StatDisplay.GEMS_EARNED },
|
||||
|
@ -64,7 +64,16 @@ public class PetTagPage extends ShopPageBase<CosmeticManager, CosmeticShop>
|
||||
{
|
||||
_tagName = ChatColor.stripColor(_tagName);
|
||||
_tagName = _tagName.replaceAll("[^A-Za-z0-9]", "");
|
||||
|
||||
System.out.println("Pet name: " + _tagName + ".");
|
||||
if (_tagName.length() == 0)
|
||||
{
|
||||
UtilPlayer.message(getPlayer(), F.main(getPlugin().getName(), ChatColor.RED + "Supplied pet name contains invalid characters."));
|
||||
playDenySound(getPlayer());
|
||||
|
||||
getShop().openPageForPlayer(getPlayer(), new PetPage(getPlugin(), getShop(), getClientManager(), getDonationManager(), "Pets", getPlayer()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tagName.length() > 16)
|
||||
{
|
||||
UtilPlayer.message(getPlayer(), F.main(getPlugin().getName(), ChatColor.RED + "Pet name cannot be longer than 16 characters."));
|
||||
|
@ -21,7 +21,7 @@ public class ParticleLegend extends ParticleGadget
|
||||
{
|
||||
super(manager, "Legendary Aura", new String[]
|
||||
{
|
||||
C.cWhite + "These mystic particle attach to",
|
||||
C.cWhite + "This mystic particle attaches to",
|
||||
C.cWhite + "only the most legendary of players!",
|
||||
" ",
|
||||
C.cGreen + "Unlocked with Legend Rank",
|
||||
|
@ -17,7 +17,7 @@ public class Ignore extends CommandBase<IgnoreManager>
|
||||
@Override
|
||||
public void Execute(final Player caller, final String[] args)
|
||||
{
|
||||
if (args == null)
|
||||
if (args == null || args.length < 1)
|
||||
{
|
||||
Plugin.showIgnores(caller);
|
||||
}
|
||||
|
@ -15,7 +15,9 @@ import org.bukkit.inventory.meta.SkullMeta;
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.game.GameDisplay;
|
||||
@ -78,17 +80,8 @@ public class ServerNpcPage extends ShopPageInventory<ServerManager, ServerNpcSho
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
if (_onMainPage)
|
||||
{
|
||||
addButton(4, ItemStackFactory.Instance.CreateStack(Material.DIAMOND_BLOCK, (byte) 0, 1, C.cGreen + "Click to join instantly!"), new IButton() {
|
||||
|
||||
@Override
|
||||
public void onClick(Player player, ClickType clickType) {
|
||||
getPlugin().selectServer(player, _serverGroupName);
|
||||
}
|
||||
});
|
||||
|
||||
buildAvailableServerPage(serverList, slotsNeeded);
|
||||
}
|
||||
else
|
||||
@ -108,7 +101,7 @@ public class ServerNpcPage extends ShopPageInventory<ServerManager, ServerNpcSho
|
||||
ChatColor.RESET + timeLeft + " Remaining...",
|
||||
ChatColor.RESET + "",
|
||||
ChatColor.RESET + C.cGreen + "Do you love playing on Mineplex?",
|
||||
ChatColor.RESET + "If you do, please consider purchasing Ultra or Hero",
|
||||
ChatColor.RESET + "If you do, please consider purchasing a premium rank",
|
||||
ChatColor.RESET + "from the store! Money goes towards running servers",
|
||||
ChatColor.RESET + "and creating exciting new games for everyone!",
|
||||
ChatColor.RESET + "",
|
||||
@ -297,15 +290,25 @@ public class ServerNpcPage extends ShopPageInventory<ServerManager, ServerNpcSho
|
||||
}
|
||||
}
|
||||
|
||||
addButton(40, new ShopItem(Material.GOLD_BLOCK, C.cAqua + yellowCount + " Game" + (yellowCount == 1 ? "" : "s") + " In Progress", new String[]{MESSAGE_SPECTATE}, yellowCount > 64 ? 64 : yellowCount, false), new IButton()
|
||||
{
|
||||
@Override
|
||||
public void onClick(Player player, ClickType clickType)
|
||||
if(showGreen) {
|
||||
addButton(40, new ShopItem(Material.GOLD_BLOCK, C.cAqua + yellowCount + " Game" + (yellowCount == 1 ? "" : "s") + " In Progress", new String[]{MESSAGE_SPECTATE}, yellowCount > 64 ? 64 : yellowCount, false), new IButton()
|
||||
{
|
||||
_onMainPage = false;
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onClick(Player player, ClickType clickType)
|
||||
{
|
||||
_onMainPage = false;
|
||||
}
|
||||
});
|
||||
|
||||
addButton(4, ItemStackFactory.Instance.CreateStack(Material.DIAMOND_BLOCK, (byte) 0, 1, C.cGreen + "Click to join instantly!"), new IButton() {
|
||||
|
||||
@Override
|
||||
public void onClick(Player player, ClickType clickType) {
|
||||
getPlugin().selectServer(player, _serverGroupName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Clear empty slots
|
||||
if (showGreen)
|
||||
{
|
||||
|
@ -134,9 +134,30 @@ public class Flash extends SkillActive
|
||||
while (curRange <= maxRange)
|
||||
{
|
||||
Location newTarget = player.getLocation().add(new Vector(0,0.2,0)).add(player.getLocation().getDirection().multiply(curRange));
|
||||
|
||||
if (!UtilBlock.airFoliage(newTarget.getBlock()) ||
|
||||
!UtilBlock.airFoliage(newTarget.getBlock().getRelative(BlockFace.UP)))
|
||||
Location aboveTarget = newTarget.getBlock().getRelative(BlockFace.UP).getLocation();
|
||||
|
||||
// half-slab
|
||||
boolean newTargetIsSlab = newTarget.getBlock().getType() == Material.STEP || newTarget.getBlock().getType() == Material.WOOD_STEP;
|
||||
boolean aboveTargetIsSlab = aboveTarget.getBlock().getType() == Material.STEP || aboveTarget.getBlock().getType() == Material.WOOD_STEP;
|
||||
|
||||
boolean newTargetSlabIsBottom = false;
|
||||
boolean aboveTargetSlabIsBottom = false;
|
||||
|
||||
if(newTargetIsSlab && curRange < 0.5)
|
||||
{
|
||||
int newTargetData = (int) newTarget.getBlock().getData();
|
||||
|
||||
if(newTargetData <= 7) newTargetSlabIsBottom = true;
|
||||
}
|
||||
|
||||
if(aboveTargetIsSlab && curRange < 0.25)
|
||||
{
|
||||
int aboveTargetData = (int) aboveTarget.getBlock().getData();
|
||||
|
||||
if(aboveTargetData <= 7) aboveTargetSlabIsBottom = true;
|
||||
}
|
||||
|
||||
if ((!newTargetSlabIsBottom && UtilBlock.fullSolid(newTarget.getBlock())) || (!aboveTargetSlabIsBottom && UtilBlock.fullSolid(aboveTarget.getBlock())))
|
||||
break;
|
||||
|
||||
//Progress Forwards
|
||||
|
@ -84,6 +84,9 @@ public class ShieldSmash extends SkillActive
|
||||
|
||||
if (cur.equals(player))
|
||||
continue;
|
||||
|
||||
if (UtilPlayer.isSpectator(cur))
|
||||
continue;
|
||||
|
||||
if (UtilMath.offset(loc, cur.getLocation()) > 2.5)
|
||||
continue;
|
||||
|
@ -94,13 +94,16 @@ public class FissureData
|
||||
_loc.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId());
|
||||
|
||||
//Slow
|
||||
for (Player cur : block.getWorld().getPlayers())
|
||||
for (Player cur : block.getWorld().getPlayers()) {
|
||||
if(UtilPlayer.isSpectator(cur)) continue;
|
||||
|
||||
if (!cur.equals(_player))
|
||||
if (UtilMath.offset(block.getLocation().add(0.5, 0.5, 0.5), cur.getLocation()) < 1.5)
|
||||
{
|
||||
//Condition
|
||||
Host.Factory.Condition().Factory().Slow("Fissure", cur, _player, 1 + _level, 1, false, true, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +149,10 @@ public class FissureData
|
||||
up.getWorld().playEffect(up.getLocation(), Effect.STEP_SOUND, block.getTypeId());
|
||||
|
||||
//Damage
|
||||
for (Player cur : up.getWorld().getPlayers())
|
||||
for (Player cur : up.getWorld().getPlayers()) {
|
||||
if (UtilPlayer.isSpectator(cur))
|
||||
continue;
|
||||
|
||||
if (!cur.equals(_player))
|
||||
{
|
||||
//Teleport
|
||||
@ -172,7 +178,7 @@ public class FissureData
|
||||
UtilPlayer.message(cur, F.main(Host.GetClassType().name(), F.name(_player.getName()) +" hit you with " + F.skill(Host.GetName(_level)) + "."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//Next Column
|
||||
if (_height >= Math.min(3, _handled/2 + 1))
|
||||
{
|
||||
|
@ -358,27 +358,6 @@ public class MonsterMaze extends SoloGame
|
||||
}
|
||||
}
|
||||
|
||||
private boolean _announced = false;
|
||||
@EventHandler
|
||||
public void sendF5Message(UpdateEvent event)
|
||||
{
|
||||
if (event.getType() != UpdateType.FASTEST)
|
||||
return;
|
||||
|
||||
if (GetState() != GameState.Prepare)
|
||||
return;
|
||||
|
||||
if (_announced)
|
||||
return;
|
||||
|
||||
if (!UtilTime.elapsed(GetStateTime(), 4000))
|
||||
return;
|
||||
|
||||
_announced = true;
|
||||
UtilTextMiddle.display(C.cYellow + C.Bold + "Press F5", C.cAqua + C.Bold + "Monster Maze is best in 3rd person!");
|
||||
Announce(C.cYellow + C.Scramble + "@@" + C.cAqua + C.Bold + " Monster Maze is best played in 3rd Person! (Push F5) " + C.cYellow + C.Scramble + "@@");
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventHandler
|
||||
public void ScoreboardUpdate(UpdateEvent event)
|
||||
|
@ -61,7 +61,7 @@ public class KitCreeper extends SmashKit
|
||||
}));
|
||||
|
||||
player.getInventory().addItem(ItemStackFactory.Instance.CreateStack(Material.IRON_SPADE, (byte)0, 1,
|
||||
C.cYellow + C.Bold + "Right-Click" + C.cWhite + C.Bold + " - " + C.cGreen + C.Bold + "Explosive Leap",
|
||||
C.cYellow + C.Bold + "Right-Click" + C.cWhite + C.Bold + " - " + C.cGreen + C.Bold + "Explode",
|
||||
new String[]
|
||||
{
|
||||
ChatColor.RESET + "You freeze in location and charge up",
|
||||
|
@ -13,10 +13,10 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.UtilParticle;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTextMiddle;
|
||||
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTextMiddle;
|
||||
import mineplex.core.recharge.Recharge;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
@ -37,10 +37,13 @@ public class PerkEndermanTeleport extends SmashPerk
|
||||
|
||||
@EventHandler
|
||||
public void update(UpdateEvent event)
|
||||
{
|
||||
{
|
||||
if (event.getType() != UpdateType.TICK)
|
||||
return;
|
||||
|
||||
if(!Manager.GetGame().IsLive())
|
||||
return;
|
||||
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
if (!Kit.HasKit(player))
|
||||
@ -88,7 +91,7 @@ public class PerkEndermanTeleport extends SmashPerk
|
||||
}
|
||||
|
||||
player.playSound(player.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 0.5f);
|
||||
player.teleport(block.getLocation().add(0.5, 1, 0.5));
|
||||
player.teleport(block.getLocation().add(0.5, 1, 0.5).setDirection(player.getLocation().getDirection()));
|
||||
player.playSound(player.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 0.5f);
|
||||
|
||||
UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, player.getLocation().add(0, 1, 0), 1f, 1f, 1f, 0.1f, 100, ViewDist.LONG, UtilServer.getPlayers());
|
||||
|
@ -941,7 +941,7 @@ public abstract class SurvivalGames extends Game
|
||||
|
||||
for (Player alive : GetPlayers(true))
|
||||
{
|
||||
if (alive != player)
|
||||
if (alive != player && getArcadeManager().canHurt(player, alive))
|
||||
{
|
||||
double distance = alive.getLocation().distance(
|
||||
player.getLocation());
|
||||
@ -1838,6 +1838,9 @@ public abstract class SurvivalGames extends Game
|
||||
|
||||
if (!UtilInv.IsItem(player.getItemInHand(), Material.TNT, (byte) 0))
|
||||
return;
|
||||
|
||||
if(!IsAlive(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
|
@ -11,7 +11,7 @@ public class GiveAdminPage extends PlayerPage
|
||||
{
|
||||
public GiveAdminPage(ArcadeManager plugin, PrivateServerShop shop, Player player)
|
||||
{
|
||||
super(plugin, shop, "Give Admin", player);
|
||||
super(plugin, shop, "Give Co-Host", player);
|
||||
buildPage();
|
||||
}
|
||||
|
||||
@ -26,12 +26,12 @@ public class GiveAdminPage extends PlayerPage
|
||||
{
|
||||
removeButton(slot);
|
||||
_manager.giveAdmin(player);
|
||||
UtilPlayer.message(getPlayer(), F.main("Server", "You gave " + F.name(player.getName()) + " admin power."));
|
||||
UtilPlayer.message(getPlayer(), F.main("Server", "You gave " + F.name(player.getName()) + " Co-Host power."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayString(Player player)
|
||||
{
|
||||
return "Click to Make Admin";
|
||||
return "Click to Make Co-Host";
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ public class RemoveAdminPage extends BasePage
|
||||
{
|
||||
public RemoveAdminPage(ArcadeManager plugin, PrivateServerShop shop, Player player)
|
||||
{
|
||||
super(plugin, shop, "Remove Admin", player);
|
||||
super(plugin, shop, "Remove Co-Host", player);
|
||||
|
||||
buildPage();
|
||||
}
|
||||
@ -36,7 +36,7 @@ public class RemoveAdminPage extends BasePage
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
String name = iterator.next();
|
||||
ItemStack head = getPlayerHead(name, C.cGreen + C.Bold + name, new String[] {ChatColor.RESET + C.cGray + "Click to Remove Admin"});
|
||||
ItemStack head = getPlayerHead(name, C.cGreen + C.Bold + name, new String[] {ChatColor.RESET + C.cGray + "Click to Remove Co-Host"});
|
||||
addButton(slot, head, getRemoveAdminButton(slot, name));
|
||||
|
||||
slot++;
|
||||
@ -52,7 +52,7 @@ public class RemoveAdminPage extends BasePage
|
||||
{
|
||||
_manager.removeAdmin(playerName);
|
||||
removeButton(slot);
|
||||
UtilPlayer.message(getPlayer(), F.main("Server", "You removed admin power from " + F.name(playerName) + "."));
|
||||
UtilPlayer.message(getPlayer(), F.main("Server", "You removed Co-Host power from " + F.name(playerName) + "."));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package nautilus.game.arcade.kit.perks;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
@ -109,7 +110,9 @@ public class PerkBaconBlast extends Perk implements IThrown
|
||||
|
||||
public void Explode(ProjectileUser data)
|
||||
{
|
||||
data.GetThrown().getWorld().createExplosion(data.GetThrown().getLocation(), 0.5f);
|
||||
// for whatever reason, you can't put a location in createExplosion if you don't want it to break blocks >.>
|
||||
Location loc = data.GetThrown().getLocation();
|
||||
data.GetThrown().getWorld().createExplosion(loc.getX(), loc.getY(), loc.getZ(), 0.5f, false, false);
|
||||
data.GetThrown().remove();
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,10 @@ public class PerkBladeVortex extends Perk
|
||||
|
||||
if (!UtilGear.isWeapon(event.getPlayer().getItemInHand()))
|
||||
return;
|
||||
|
||||
//Dont allow usage in early game
|
||||
if (!UtilTime.elapsed(Manager.GetGame().GetStateTime(), 30000))
|
||||
return;
|
||||
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
|
@ -125,7 +125,7 @@ public class PerkDoubleJump extends Perk
|
||||
if (!Recharge.Instance.usable(player, "Double Jump"))
|
||||
continue;
|
||||
|
||||
if (UtilEnt.isGrounded(player) || UtilBlock.solid(player.getLocation().getBlock().getRelative(BlockFace.DOWN)))
|
||||
if (player.isOnGround() || (UtilBlock.solid(player.getLocation().getBlock().getRelative(BlockFace.DOWN)) && UtilBlock.solid(player.getLocation().getBlock())))
|
||||
player.setAllowFlight(true);
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ public class PerkFlameDash extends Perk
|
||||
|
||||
_data.add(new FireflyData(player));
|
||||
|
||||
Manager.GetCondition().Factory().Invisible(GetName(), player, player, 2.5, 0, false, false, true);
|
||||
Manager.GetCondition().Factory().Cloak(GetName(), player, player, 2.5, false, false);
|
||||
//Manager.GetCondition().Factory().Invisible(GetName(), player, player, 2.5, 0, false, false, true);
|
||||
|
||||
UtilPlayer.message(player, F.main("Skill", "You used " + F.skill(GetName()) + "."));
|
||||
}
|
||||
|
@ -109,6 +109,8 @@ public class PerkWitchPotion extends SmashPerk
|
||||
Manager.GetDamage().NewDamageEvent(player, thrower, null,
|
||||
DamageCause.CUSTOM, 5, true, true, false,
|
||||
UtilEnt.getName((LivingEntity)event.getEntity().getShooter()), GetName());
|
||||
|
||||
Manager.GetCondition().Factory().Slow("Witch Potion", player, null, 3, 1, true, false, false, false);
|
||||
}
|
||||
//Super Effect
|
||||
else
|
||||
@ -121,6 +123,7 @@ public class PerkWitchPotion extends SmashPerk
|
||||
DamageCause.CUSTOM, 5 + bonus, true, true, false,
|
||||
UtilEnt.getName((LivingEntity)event.getEntity().getShooter()), GetName());
|
||||
|
||||
Manager.GetCondition().Factory().Slow("Witch Potion", player, null, 7, 2, true, false, false, false);
|
||||
//Manager.GetCondition().Factory().Confuse(reason, ent, source, duration, mult, extend, showIndicator, ambient)
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ public class GameHostManager implements Listener
|
||||
|
||||
if (!isAdmin(event.getPlayer(), true))
|
||||
{
|
||||
event.getPlayer().sendMessage(F.main("Broadcast", "Only MPS admins can use this command."));
|
||||
event.getPlayer().sendMessage(F.main("Broadcast", "Only Co-Hosts can use this command."));
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
@ -46,6 +46,11 @@ public class DeathBomberStatTracker extends StatTracker<Game>
|
||||
|
||||
if (!event.GetLog().GetPlayer().IsPlayer())
|
||||
return;
|
||||
|
||||
Player killed = UtilPlayer.searchExact(event.GetLog().GetPlayer().GetName());
|
||||
|
||||
if(killer.equals(killed))
|
||||
return;
|
||||
|
||||
if (event.GetLog().GetKiller() != null && event.GetLog().GetKiller().GetReason().contains("Throwing TNT"))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user