Work on the actual jailing of the player.
Lots of work done here, untested.
This commit is contained in:
parent
7e614a121f
commit
a72f6c273b
@ -19,6 +19,8 @@ Done
|
|||||||
* The time passed can be represented by time shorthand, aka "3hours" or "15minutes" or etc (defaults to minutes)
|
* The time passed can be represented by time shorthand, aka "3hours" or "15minutes" or etc (defaults to minutes)
|
||||||
* Config value ``jailing.jail.broadcastJailing`` is now used
|
* Config value ``jailing.jail.broadcastJailing`` is now used
|
||||||
* Config value ``jailing.jail.logToConsole`` is now used
|
* Config value ``jailing.jail.logToConsole`` is now used
|
||||||
|
* Config value ``jailing.jail.deleteInventory`` is now used
|
||||||
|
* Config value ``jailing.release.backToPreviousPosition`` is now used
|
||||||
|
|
||||||
[Jail 3.0 JavaDoc](http://ci.graywolf336.com/job/Jail/javadoc)
|
[Jail 3.0 JavaDoc](http://ci.graywolf336.com/job/Jail/javadoc)
|
||||||
====
|
====
|
@ -215,6 +215,8 @@ public class JailIO {
|
|||||||
flat.set(cNode + "prisoner.muted", p.isMuted());
|
flat.set(cNode + "prisoner.muted", p.isMuted());
|
||||||
flat.set(cNode + "prisoner.time", p.getRemainingTime());
|
flat.set(cNode + "prisoner.time", p.getRemainingTime());
|
||||||
flat.set(cNode + "prisoner.offlinePending", p.isOfflinePending());
|
flat.set(cNode + "prisoner.offlinePending", p.isOfflinePending());
|
||||||
|
flat.set(cNode + "prisoner.reason", p.getReason());
|
||||||
|
flat.set(cNode + "prisoner.previousLocation", p.getPreviousLocationString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +225,8 @@ public class JailIO {
|
|||||||
flat.set(pNode + "muted", p.isMuted());
|
flat.set(pNode + "muted", p.isMuted());
|
||||||
flat.set(pNode + "time", p.getRemainingTime());
|
flat.set(pNode + "time", p.getRemainingTime());
|
||||||
flat.set(pNode + "offlinePending", p.isOfflinePending());
|
flat.set(pNode + "offlinePending", p.isOfflinePending());
|
||||||
|
flat.set(pNode + "reason", p.getReason());
|
||||||
|
flat.set(pNode + "previousLocation", p.getPreviousLocationString());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -296,30 +300,30 @@ public class JailIO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(flat.contains(cellNode + "prisoner")) {
|
if(flat.contains(cellNode + "prisoner")) {
|
||||||
Prisoner p = new Prisoner(flat.getString(cellNode + "prisoner.name"), flat.getBoolean(cellNode + "prisoner.muted"), flat.getLong(cellNode + "prisoner.time"));
|
Prisoner p = new Prisoner(flat.getString(cellNode + "prisoner.name"),
|
||||||
|
flat.getBoolean(cellNode + "prisoner.muted"),
|
||||||
|
flat.getLong(cellNode + "prisoner.time"),
|
||||||
|
flat.getString(cellNode + "prisoner.reason"));
|
||||||
p.setOfflinePending(flat.getBoolean(cellNode + "prisoner.offlinePending"));
|
p.setOfflinePending(flat.getBoolean(cellNode + "prisoner.offlinePending"));
|
||||||
|
p.setPreviousPosition(flat.getString(cellNode + "prisoner.previousLocation"));
|
||||||
c.setPrisoner(p);
|
c.setPrisoner(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
j.addCell(c, false);
|
j.addCell(c, false);
|
||||||
}
|
}
|
||||||
}else {
|
|
||||||
pl.getLogger().warning("Cell configuration section for " + name + " exists but no cells are there.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flat.isConfigurationSection(node + "prisoners")) {
|
if(flat.isConfigurationSection(node + "prisoners")) {
|
||||||
Set<String> prisoners = flat.getConfigurationSection(node + "prisoners").getKeys(false);
|
Set<String> prisoners = flat.getConfigurationSection(node + "prisoners").getKeys(false);
|
||||||
if(!prisoners.isEmpty()) {
|
if(!prisoners.isEmpty()) {
|
||||||
pl.getLogger().info("Prisoner configuration section for " + j.getName() + " exists and there are " + prisoners.size() + " prisoners.");
|
|
||||||
for(String prisoner : prisoners) {
|
for(String prisoner : prisoners) {
|
||||||
String pNode = node + "prisoners." + prisoner + ".";
|
String pNode = node + "prisoners." + prisoner + ".";
|
||||||
Prisoner pris = new Prisoner(prisoner, flat.getBoolean(pNode + "muted"), flat.getLong(pNode + "time"));
|
Prisoner pris = new Prisoner(prisoner, flat.getBoolean(pNode + "muted"), flat.getLong(pNode + "time"), flat.getString(pNode + "reason"));
|
||||||
pris.setOfflinePending(flat.getBoolean(pNode + "offlinePending"));
|
pris.setOfflinePending(flat.getBoolean(pNode + "offlinePending"));
|
||||||
|
pris.setPreviousPosition(flat.getString(pNode + "previousLocation"));
|
||||||
j.addPrisoner(pris);
|
j.addPrisoner(pris);
|
||||||
}
|
}
|
||||||
}else {
|
|
||||||
pl.getLogger().warning("Prisoner configuration section for " + j.getName() + "exists but there are no prisoners.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class PrisonerManager {
|
|||||||
|
|
||||||
//If they are NOT offline, jail them
|
//If they are NOT offline, jail them
|
||||||
if(!prisoner.isOfflinePending()) {
|
if(!prisoner.isOfflinePending()) {
|
||||||
|
jailPrisoner(jail, cell, player, prisoner);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get a message ready for broadcasting or logging.
|
//Get a message ready for broadcasting or logging.
|
||||||
@ -70,4 +70,51 @@ public class PrisonerManager {
|
|||||||
pl.getServer().getConsoleSender().sendMessage(msg);
|
pl.getServer().getConsoleSender().sendMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jails the prisoner with the given name.
|
||||||
|
*
|
||||||
|
* @param name of the prisoner to jail.
|
||||||
|
*/
|
||||||
|
public void jailPrisoner(String name) {
|
||||||
|
Jail j = pl.getJailManager().getJailPlayerIsIn(name);
|
||||||
|
|
||||||
|
jailPrisoner(j, j.getCellPrisonerIsIn(name), pl.getServer().getPlayerExact(name), j.getPrisoner(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jails the prisoner with the proper information given.
|
||||||
|
*
|
||||||
|
* @param jail where they are going
|
||||||
|
* @param cell where they are being placed in, can be null
|
||||||
|
* @param player who is the prisoner
|
||||||
|
* @param prisoner data containing everything pertaining to them
|
||||||
|
*/
|
||||||
|
public void jailPrisoner(Jail jail, Cell cell, Player player, Prisoner prisoner) {
|
||||||
|
//They are no longer offline, so set that.
|
||||||
|
prisoner.setOfflinePending(false);
|
||||||
|
|
||||||
|
//We are getting ready to teleport them, so set it to true so that
|
||||||
|
//the *future* move checkers won't be cancelling our moving.
|
||||||
|
prisoner.setTeleporting(true);
|
||||||
|
|
||||||
|
//If their reason is empty send proper message, else send other proper message
|
||||||
|
if(prisoner.getReason().isEmpty()) {
|
||||||
|
player.sendMessage(pl.getJailIO().getLanguageString(LangString.JAILED));
|
||||||
|
}else {
|
||||||
|
player.sendMessage(pl.getJailIO().getLanguageString(LangString.JAILEDWITHREASON, new String[] { prisoner.getReason() }));
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the config has inventory deletion, then let's delete it
|
||||||
|
if(pl.getConfig().getBoolean(Settings.DELETEINVENTORY.getPath(), false)) {
|
||||||
|
player.getInventory().setArmorContents(null);
|
||||||
|
player.getInventory().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the config has releasing them back to their previous position,
|
||||||
|
//then let's set it in the prisoner data.
|
||||||
|
if(pl.getConfig().getBoolean(Settings.RELEASETOPREVIOUSPOSITION.getPath(), false)) {
|
||||||
|
prisoner.setPreviousPosition(player.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,16 @@ public class Jail {
|
|||||||
return this.cells.get(name);
|
return this.cells.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the cell which the given player name is jailed in, null if not. */
|
||||||
|
public Cell getCellPrisonerIsIn(String name) {
|
||||||
|
for(Cell c : cells.values())
|
||||||
|
if(c.getPrisoner() != null)
|
||||||
|
if(c.getPrisoner().getName().equalsIgnoreCase(name))
|
||||||
|
return c;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the first empty cell, returns null if there aren't any cells or any free cells. */
|
/** Returns the first empty cell, returns null if there aren't any cells or any free cells. */
|
||||||
public Cell getFirstEmptyCell() {
|
public Cell getFirstEmptyCell() {
|
||||||
for(Cell c : getCells())
|
for(Cell c : getCells())
|
||||||
@ -232,6 +242,25 @@ public class Jail {
|
|||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given name is a prisoner in a cell.
|
||||||
|
*
|
||||||
|
* @param name of the prisoner to check.
|
||||||
|
* @return true if is jailed in a cell, false if not.
|
||||||
|
*/
|
||||||
|
public boolean isJailedInACell(String name) {
|
||||||
|
for(Prisoner p : nocellPrisoners)
|
||||||
|
if(p.getName().equalsIgnoreCase(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(Cell c : cells.values())
|
||||||
|
if(c.getPrisoner() != null)
|
||||||
|
if(c.getPrisoner().getName().equalsIgnoreCase(name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link Prisoner prisoner} instance for the given name.
|
* Gets the {@link Prisoner prisoner} instance for the given name.
|
||||||
*
|
*
|
||||||
|
@ -2,6 +2,9 @@ package com.graywolf336.jail.beans;
|
|||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Prisoner, player who is jailed, and contains all the information about him/her.
|
* Represents a Prisoner, player who is jailed, and contains all the information about him/her.
|
||||||
*
|
*
|
||||||
@ -10,9 +13,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* @version 2.0.1
|
* @version 2.0.1
|
||||||
*/
|
*/
|
||||||
public class Prisoner {
|
public class Prisoner {
|
||||||
private String name;
|
private String name, reason;
|
||||||
private boolean muted, offlinePending;
|
private boolean muted, offlinePending, teleporting;
|
||||||
private long time;
|
private long time;
|
||||||
|
private Location previousPosition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new prisoner with a name and whether they are muted or not.
|
* Creates a new prisoner with a name and whether they are muted or not.
|
||||||
@ -21,10 +25,14 @@ public class Prisoner {
|
|||||||
* @param muted Whether the prisoner is muted or not
|
* @param muted Whether the prisoner is muted or not
|
||||||
* @param time The amount of remaining time the prisoner has
|
* @param time The amount of remaining time the prisoner has
|
||||||
*/
|
*/
|
||||||
public Prisoner(String name, boolean muted, long time) {
|
public Prisoner(String name, boolean muted, long time, String reason) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.muted = muted;
|
this.muted = muted;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
|
this.reason = reason;
|
||||||
|
this.offlinePending = false;
|
||||||
|
this.teleporting = false;
|
||||||
|
this.previousPosition = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the name of this player. */
|
/** Gets the name of this player. */
|
||||||
@ -32,6 +40,16 @@ public class Prisoner {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets the reason this player was jailed for. */
|
||||||
|
public String getReason() {
|
||||||
|
return this.reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the reason this player was jailed for. */
|
||||||
|
public void setReason(String reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets whether the prisoner is muted or not. */
|
/** Gets whether the prisoner is muted or not. */
|
||||||
public boolean isMuted() {
|
public boolean isMuted() {
|
||||||
return this.muted;
|
return this.muted;
|
||||||
@ -70,4 +88,46 @@ public class Prisoner {
|
|||||||
public void setOfflinePending(boolean offline) {
|
public void setOfflinePending(boolean offline) {
|
||||||
this.offlinePending = offline;
|
this.offlinePending = offline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets whether the player is being teleported or not. */
|
||||||
|
public boolean isTeleporting() {
|
||||||
|
return this.teleporting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets whether the player is being teleported or not. */
|
||||||
|
public void setTeleporting(boolean teleport) {
|
||||||
|
this.teleporting = teleport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the previous location of this player, can be null. */
|
||||||
|
public Location getPreviousLocation() {
|
||||||
|
return this.previousPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the previous location of this player, separated by a comma. */
|
||||||
|
public String getPreviousLocationString() {
|
||||||
|
if(previousPosition == null) return "";
|
||||||
|
else return previousPosition.getWorld().getName() + "," +
|
||||||
|
previousPosition.getX() + "," +
|
||||||
|
previousPosition.getY() + "," +
|
||||||
|
previousPosition.getZ() + "," +
|
||||||
|
previousPosition.getYaw() + "," +
|
||||||
|
previousPosition.getPitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the previous location of this player. */
|
||||||
|
public void setPreviousPosition(Location location) {
|
||||||
|
this.previousPosition = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the previous location of this player from a comma separated string. */
|
||||||
|
public void setPreviousPosition(String location) {
|
||||||
|
String[] s = location.split(",");
|
||||||
|
this.previousPosition = new Location(Bukkit.getWorld(s[0]),
|
||||||
|
Double.valueOf(s[1]),
|
||||||
|
Double.valueOf(s[2]),
|
||||||
|
Double.valueOf(s[3]),
|
||||||
|
Float.valueOf(s[4]),
|
||||||
|
Float.valueOf(s[5]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,10 +98,10 @@ public class JailCommand implements Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the jail instance from the name of jail in the params.
|
if(params.reason().isEmpty()) {
|
||||||
Jail j = jm.getJail(params.jail());
|
params.setReason(jm.getPlugin().getJailIO().getLanguageString(LangString.DEFAULTJAILEDREASON));
|
||||||
Cell c = j.getCell(params.cell());
|
}
|
||||||
Prisoner pris = new Prisoner(params.player(), params.muted(), time);
|
|
||||||
Player p = jm.getPlugin().getServer().getPlayer(params.player());
|
Player p = jm.getPlugin().getServer().getPlayer(params.player());
|
||||||
|
|
||||||
//If the player instance is not null and the player has the permission
|
//If the player instance is not null and the player has the permission
|
||||||
@ -111,6 +111,11 @@ public class JailCommand implements Command {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get the jail instance from the name of jail in the params.
|
||||||
|
Jail j = jm.getJail(params.jail());
|
||||||
|
Cell c = j.getCell(params.cell());
|
||||||
|
Prisoner pris = new Prisoner(params.player(), params.muted(), time, params.reason());
|
||||||
|
|
||||||
//call the event
|
//call the event
|
||||||
PrisonerJailedEvent event = new PrisonerJailedEvent(j, c, pris, p, p == null, sender.getName());
|
PrisonerJailedEvent event = new PrisonerJailedEvent(j, c, pris, p, p == null, sender.getName());
|
||||||
jm.getPlugin().getServer().getPluginManager().callEvent(event);
|
jm.getPlugin().getServer().getPluginManager().callEvent(event);
|
||||||
@ -147,12 +152,6 @@ public class JailCommand implements Command {
|
|||||||
//Player *is* online
|
//Player *is* online
|
||||||
sender.sendMessage(pris.getName() + " is online and will be jailed for " + pris.getRemainingTime() + " milliseconds in the jail " + params.jail() + " in the cell " + params.cell() + " and will be muted: " + pris.isMuted() + ".");
|
sender.sendMessage(pris.getName() + " is online and will be jailed for " + pris.getRemainingTime() + " milliseconds in the jail " + params.jail() + " in the cell " + params.cell() + " and will be muted: " + pris.isMuted() + ".");
|
||||||
sender.sendMessage(pris.getName() + " will be jailed for " + TimeUnit.MINUTES.convert(pris.getRemainingTime(), TimeUnit.MILLISECONDS) + " minutes by " + jailer + ".");
|
sender.sendMessage(pris.getName() + " will be jailed for " + TimeUnit.MINUTES.convert(pris.getRemainingTime(), TimeUnit.MILLISECONDS) + " minutes by " + jailer + ".");
|
||||||
|
|
||||||
if(params.reason().isEmpty()) {
|
|
||||||
p.sendMessage(jm.getPlugin().getJailIO().getLanguageString(LangString.JAILED));
|
|
||||||
}else {
|
|
||||||
p.sendMessage(jm.getPlugin().getJailIO().getLanguageString(LangString.JAILEDWITHREASON, new String[] { params.reason() }));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -93,4 +93,13 @@ public class JailParameters {
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the reason. */
|
||||||
|
public void setReason(String r) {
|
||||||
|
String[] rs = r.split(" ");
|
||||||
|
|
||||||
|
for(String s : rs) {
|
||||||
|
reason.add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ public enum LangString {
|
|||||||
BROADCASTMESSAGEFORMINUTES,
|
BROADCASTMESSAGEFORMINUTES,
|
||||||
/** The message sent when trying to jail someone who can't be jailed by permission. */
|
/** The message sent when trying to jail someone who can't be jailed by permission. */
|
||||||
CANTBEJAILED,
|
CANTBEJAILED,
|
||||||
|
/** The message sent when someone is jailed without a reason. */
|
||||||
|
DEFAULTJAILEDREASON,
|
||||||
/** The message sent when players are jailed without a reason. */
|
/** The message sent when players are jailed without a reason. */
|
||||||
JAILED,
|
JAILED,
|
||||||
/** The message sent when players are jailed with a reason. */
|
/** The message sent when players are jailed with a reason. */
|
||||||
|
@ -4,8 +4,10 @@ public enum Settings {
|
|||||||
BROADCASTJAILING("jailing.jail.broadcastJailing"),
|
BROADCASTJAILING("jailing.jail.broadcastJailing"),
|
||||||
DEBUG("system.debug"),
|
DEBUG("system.debug"),
|
||||||
DEFAULTJAIL("jailing.jail.defaultJail"),
|
DEFAULTJAIL("jailing.jail.defaultJail"),
|
||||||
|
DELETEINVENTORY("jailing.jail.deleteInventory"),
|
||||||
JAILDEFAULTTIME("jailing.jail.defaultTime"),
|
JAILDEFAULTTIME("jailing.jail.defaultTime"),
|
||||||
LOGJAILING("jailing.jail.logToConsole"),
|
LOGJAILING("jailing.jail.logToConsole"),
|
||||||
|
RELEASETOPREVIOUSPOSITION("jailing.release.backToPreviousPosition"),
|
||||||
UPDATENOTIFICATIONS("system.updateNotifications");
|
UPDATENOTIFICATIONS("system.updateNotifications");
|
||||||
|
|
||||||
private String path;
|
private String path;
|
||||||
|
@ -8,6 +8,7 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
import com.graywolf336.jail.JailMain;
|
import com.graywolf336.jail.JailMain;
|
||||||
import com.graywolf336.jail.JailManager;
|
import com.graywolf336.jail.JailManager;
|
||||||
@ -50,4 +51,13 @@ public class PlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void checkForOfflineJail(PlayerJoinEvent event) {
|
||||||
|
if(pl.getJailManager().isPlayerJailed(event.getPlayer().getName())) {
|
||||||
|
if(pl.getJailManager().getJailPlayerIsIn(event.getPlayer().getName()).getPrisoner(event.getPlayer().getName()).isOfflinePending()) {
|
||||||
|
pl.getPrisonerManager().jailPrisoner(event.getPlayer().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,3 +5,4 @@ language:
|
|||||||
broadcastmessageforever: "&9%0% has been jailed forever."
|
broadcastmessageforever: "&9%0% has been jailed forever."
|
||||||
broadcastmessageforminutes: "&9%0% has been jailed for %1% minutes."
|
broadcastmessageforminutes: "&9%0% has been jailed for %1% minutes."
|
||||||
cantbejailed: "&cThat player can't be jailed, due to permissions."
|
cantbejailed: "&cThat player can't be jailed, due to permissions."
|
||||||
|
defaultjailedreason: "Breaking the rules."
|
Loading…
Reference in New Issue
Block a user