mirror of
https://github.com/EssentialsX/Essentials.git
synced 2025-01-03 06:57:39 +01:00
Use PaperLib to load chunks and teleport players async (#2409)
* Remove outdated permission plugin handlers, minor test fixes
* Re-add PermissionEX handler
* Use PaperLib to load chunks async whenever possible
* Revert "Use PaperLib to load chunks async whenever possible"
This reverts commit db4df6f3cf
.
* Use PaperLib to load chunks and teleport players async
* Resolve some PR issues
* Update PaperLib, return teleport causes
* Remove useless PaperLib usage in LocationUtil
* Fix FakeServer spacing
This commit is contained in:
parent
f214696664
commit
3856a690eb
@ -36,6 +36,12 @@
|
|||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>io.papermc.lib</pattern>
|
||||||
|
<shadedPattern>com.earth2me.essentials.paperlib</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
@ -48,6 +54,12 @@
|
|||||||
<version>1.7</version>
|
<version>1.7</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.papermc</groupId>
|
||||||
|
<artifactId>paperlib</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.ess3</groupId>
|
<groupId>net.ess3</groupId>
|
||||||
<artifactId>NMSProvider</artifactId>
|
<artifactId>NMSProvider</artifactId>
|
||||||
@ -95,12 +107,6 @@
|
|||||||
<artifactId>ReflectionProvider</artifactId>
|
<artifactId>ReflectionProvider</artifactId>
|
||||||
<version>2.16.0</version>
|
<version>2.16.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.bukkit</groupId>
|
|
||||||
<artifactId>craftbukkit</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.ess3</groupId>
|
<groupId>net.ess3</groupId>
|
||||||
|
@ -7,6 +7,7 @@ import com.earth2me.essentials.textreader.TextPager;
|
|||||||
import com.earth2me.essentials.utils.DateUtil;
|
import com.earth2me.essentials.utils.DateUtil;
|
||||||
import com.earth2me.essentials.utils.LocationUtil;
|
import com.earth2me.essentials.utils.LocationUtil;
|
||||||
import com.earth2me.essentials.utils.MaterialUtil;
|
import com.earth2me.essentials.utils.MaterialUtil;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
import net.ess3.api.IEssentials;
|
import net.ess3.api.IEssentials;
|
||||||
|
|
||||||
import org.bukkit.BanEntry;
|
import org.bukkit.BanEntry;
|
||||||
@ -642,7 +643,7 @@ public class EssentialsPlayerListener implements Listener {
|
|||||||
while (LocationUtil.isBlockDamaging(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ())) {
|
while (LocationUtil.isBlockDamaging(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ())) {
|
||||||
loc.setY(loc.getY() + 1d);
|
loc.setY(loc.getY() + 1d);
|
||||||
}
|
}
|
||||||
user.getBase().teleport(loc, TeleportCause.PLUGIN);
|
PaperLib.teleportAsync(user.getBase(), loc, TeleportCause.PLUGIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ess.scheduleSyncDelayedTask(new DelayedClickJumpTask());
|
ess.scheduleSyncDelayedTask(new DelayedClickJumpTask());
|
||||||
|
@ -2,7 +2,9 @@ package com.earth2me.essentials;
|
|||||||
|
|
||||||
import com.earth2me.essentials.utils.DateUtil;
|
import com.earth2me.essentials.utils.DateUtil;
|
||||||
import com.earth2me.essentials.utils.LocationUtil;
|
import com.earth2me.essentials.utils.LocationUtil;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
import net.ess3.api.IEssentials;
|
import net.ess3.api.IEssentials;
|
||||||
|
import net.ess3.api.ITeleport;
|
||||||
import net.ess3.api.IUser;
|
import net.ess3.api.IUser;
|
||||||
import net.ess3.api.events.UserWarpEvent;
|
import net.ess3.api.events.UserWarpEvent;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -18,7 +20,7 @@ import java.util.GregorianCalendar;
|
|||||||
import static com.earth2me.essentials.I18n.tl;
|
import static com.earth2me.essentials.I18n.tl;
|
||||||
|
|
||||||
|
|
||||||
public class Teleport implements net.ess3.api.ITeleport {
|
public class Teleport implements ITeleport {
|
||||||
private final IUser teleportOwner;
|
private final IUser teleportOwner;
|
||||||
private final IEssentials ess;
|
private final IEssentials ess;
|
||||||
private TimedTeleport timedTeleport;
|
private TimedTeleport timedTeleport;
|
||||||
@ -49,7 +51,7 @@ public class Teleport implements net.ess3.api.ITeleport {
|
|||||||
final long earliestLong = earliestTime.getTimeInMillis();
|
final long earliestLong = earliestTime.getTimeInMillis();
|
||||||
|
|
||||||
// When was the last teleportPlayer used?
|
// When was the last teleportPlayer used?
|
||||||
final Long lastTime = teleportOwner.getLastTeleportTimestamp();
|
final long lastTime = teleportOwner.getLastTeleportTimestamp();
|
||||||
|
|
||||||
if (lastTime > time.getTimeInMillis()) {
|
if (lastTime > time.getTimeInMillis()) {
|
||||||
// This is to make sure time didn't get messed up on last teleportPlayer use.
|
// This is to make sure time didn't get messed up on last teleportPlayer use.
|
||||||
@ -124,21 +126,21 @@ public class Teleport implements net.ess3.api.ITeleport {
|
|||||||
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||||
if (ess.getSettings().isTeleportSafetyEnabled()) {
|
if (ess.getSettings().isTeleportSafetyEnabled()) {
|
||||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||||
teleportee.getBase().teleport(loc, cause);
|
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||||
} else {
|
} else {
|
||||||
teleportee.getBase().teleport(LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
|
PaperLib.teleportAsync(teleportee.getBase(), LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||||
teleportee.getBase().teleport(loc, cause);
|
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||||
} else {
|
} else {
|
||||||
if (ess.getSettings().isTeleportToCenterLocation()) {
|
if (ess.getSettings().isTeleportToCenterLocation()) {
|
||||||
loc = LocationUtil.getRoundedDestination(loc);
|
loc = LocationUtil.getRoundedDestination(loc);
|
||||||
}
|
}
|
||||||
teleportee.getBase().teleport(loc, cause);
|
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,7 +233,7 @@ public class Teleport implements net.ess3.api.ITeleport {
|
|||||||
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
|
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void respawnNow(IUser teleportee, TeleportCause cause) throws Exception {
|
void respawnNow(IUser teleportee, TeleportCause cause) throws Exception {
|
||||||
final Player player = teleportee.getBase();
|
final Player player = teleportee.getBase();
|
||||||
Location bed = player.getBedSpawnLocation();
|
Location bed = player.getBedSpawnLocation();
|
||||||
if (bed != null) {
|
if (bed != null) {
|
||||||
|
@ -16,9 +16,9 @@ public class TimedTeleport implements Runnable {
|
|||||||
private final IEssentials ess;
|
private final IEssentials ess;
|
||||||
private final Teleport teleport;
|
private final Teleport teleport;
|
||||||
private final UUID timer_teleportee;
|
private final UUID timer_teleportee;
|
||||||
private int timer_task = -1;
|
private int timer_task;
|
||||||
private final long timer_started; // time this task was initiated
|
private final long timer_started; // time this task was initiated
|
||||||
private final long timer_delay; // how long to delay the teleportPlayer
|
private final long timer_delay; // how long to delay the teleportPlayer
|
||||||
private double timer_health;
|
private double timer_health;
|
||||||
// note that I initially stored a clone of the location for reference, but...
|
// note that I initially stored a clone of the location for reference, but...
|
||||||
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
|
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
|
||||||
@ -32,8 +32,7 @@ public class TimedTeleport implements Runnable {
|
|||||||
private final Trade timer_chargeFor;
|
private final Trade timer_chargeFor;
|
||||||
private final TeleportCause timer_cause;
|
private final TeleportCause timer_cause;
|
||||||
|
|
||||||
public TimedTeleport(IUser user, IEssentials ess, Teleport teleport, long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
TimedTeleport(IUser user, IEssentials ess, Teleport teleport, long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
||||||
|
|
||||||
this.teleportOwner = user;
|
this.teleportOwner = user;
|
||||||
this.ess = ess;
|
this.ess = ess;
|
||||||
this.teleport = teleport;
|
this.teleport = teleport;
|
||||||
@ -111,8 +110,7 @@ public class TimedTeleport implements Runnable {
|
|||||||
if (timer_chargeFor != null) {
|
if (timer_chargeFor != null) {
|
||||||
timer_chargeFor.charge(teleportOwner);
|
timer_chargeFor.charge(teleportOwner);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ignored) {}
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
|
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
|
||||||
@ -124,7 +122,7 @@ public class TimedTeleport implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//If we need to cancelTimer a pending teleportPlayer call this method
|
//If we need to cancelTimer a pending teleportPlayer call this method
|
||||||
public void cancelTimer(boolean notifyUser) {
|
void cancelTimer(boolean notifyUser) {
|
||||||
if (timer_task == -1) {
|
if (timer_task == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import static com.earth2me.essentials.I18n.tl;
|
|||||||
|
|
||||||
public class LocationUtil {
|
public class LocationUtil {
|
||||||
// The player can stand inside these materials
|
// The player can stand inside these materials
|
||||||
public static final Set<Material> HOLLOW_MATERIALS = new HashSet<>();
|
private static final Set<Material> HOLLOW_MATERIALS = new HashSet<>();
|
||||||
private static final Set<Material> TRANSPARENT_MATERIALS = new HashSet<>();
|
private static final Set<Material> TRANSPARENT_MATERIALS = new HashSet<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -32,8 +32,7 @@ public class LocationUtil {
|
|||||||
TRANSPARENT_MATERIALS.add(Material.WATER);
|
TRANSPARENT_MATERIALS.add(Material.WATER);
|
||||||
try {
|
try {
|
||||||
TRANSPARENT_MATERIALS.add(Material.valueOf("FLOWING_WATER"));
|
TRANSPARENT_MATERIALS.add(Material.valueOf("FLOWING_WATER"));
|
||||||
} catch (Exception ignored) { // 1.13 WATER uses Levelled
|
} catch (Exception ignored) {} // 1.13 WATER uses Levelled
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int RADIUS = 3;
|
public static final int RADIUS = 3;
|
||||||
@ -49,7 +48,7 @@ public class LocationUtil {
|
|||||||
public int y;
|
public int y;
|
||||||
public int z;
|
public int z;
|
||||||
|
|
||||||
public Vector3D(int x, int y, int z) {
|
Vector3D(int x, int y, int z) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
@ -57,7 +56,7 @@ public class LocationUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
List<Vector3D> pos = new ArrayList<Vector3D>();
|
List<Vector3D> pos = new ArrayList<>();
|
||||||
for (int x = -RADIUS; x <= RADIUS; x++) {
|
for (int x = -RADIUS; x <= RADIUS; x++) {
|
||||||
for (int y = -RADIUS; y <= RADIUS; y++) {
|
for (int y = -RADIUS; y <= RADIUS; y++) {
|
||||||
for (int z = -RADIUS; z <= RADIUS; z++) {
|
for (int z = -RADIUS; z <= RADIUS; z++) {
|
||||||
@ -65,30 +64,22 @@ public class LocationUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(pos, new Comparator<Vector3D>() {
|
pos.sort(Comparator.comparingInt(a -> (a.x * a.x + a.y * a.y + a.z * a.z)));
|
||||||
@Override
|
|
||||||
public int compare(Vector3D a, Vector3D b) {
|
|
||||||
return (a.x * a.x + a.y * a.y + a.z * a.z) - (b.x * b.x + b.y * b.y + b.z * b.z);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
VOLUME = pos.toArray(new Vector3D[0]);
|
VOLUME = pos.toArray(new Vector3D[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static Location getTarget(final LivingEntity entity) throws Exception {
|
public static Location getTarget(final LivingEntity entity) throws Exception {
|
||||||
Block block = null;
|
Block block = null;
|
||||||
try {
|
try {
|
||||||
block = entity.getTargetBlock(TRANSPARENT_MATERIALS, 300);
|
block = entity.getTargetBlock(TRANSPARENT_MATERIALS, 300);
|
||||||
} catch (NoSuchMethodError e) {
|
} catch (NoSuchMethodError ignored) {} // failing now :(
|
||||||
// failing now :(
|
|
||||||
}
|
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
throw new Exception("Not targeting a block");
|
throw new Exception("Not targeting a block");
|
||||||
}
|
}
|
||||||
return block.getLocation();
|
return block.getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isBlockAboveAir(final World world, final int x, final int y, final int z) {
|
public static boolean isBlockAboveAir(final World world, final int x, final int y, final int z) {
|
||||||
return y > world.getMaxHeight() || HOLLOW_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType());
|
return y > world.getMaxHeight() || HOLLOW_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +115,7 @@ public class LocationUtil {
|
|||||||
if (below.getType() == Material.valueOf("FLOWING_LAVA")) {
|
if (below.getType() == Material.valueOf("FLOWING_LAVA")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) { // 1.13 LAVA uses Levelled
|
} catch (Exception ignored) {} // 1.13 LAVA uses Levelled
|
||||||
}
|
|
||||||
|
|
||||||
Material PORTAL = EnumUtil.getMaterial("NETHER_PORTAL", "PORTAL");
|
Material PORTAL = EnumUtil.getMaterial("NETHER_PORTAL", "PORTAL");
|
||||||
|
|
||||||
@ -159,7 +149,6 @@ public class LocationUtil {
|
|||||||
user.getBase().setFlying(true);
|
user.getBase().setFlying(true);
|
||||||
}
|
}
|
||||||
// ess can be null if old deprecated method is calling it.
|
// ess can be null if old deprecated method is calling it.
|
||||||
System.out.println((ess == null) + " " + ess.getSettings().isTeleportToCenterLocation());
|
|
||||||
if (ess == null || ess.getSettings().isTeleportToCenterLocation()) {
|
if (ess == null || ess.getSettings().isTeleportToCenterLocation()) {
|
||||||
return getRoundedDestination(loc);
|
return getRoundedDestination(loc);
|
||||||
} else {
|
} else {
|
||||||
|
@ -445,6 +445,10 @@ public class FakeServer implements Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public MapView getMap(short i) {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
public MapView getMap(int id) {
|
public MapView getMap(int id) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
}
|
}
|
||||||
@ -1050,7 +1054,6 @@ public class FakeServer implements Server {
|
|||||||
throw new UnsupportedOperationException("Not supported yet.");
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends Keyed> Iterable<Tag<T>> getTags(String registry, Class<T> clazz) {
|
public <T extends Keyed> Iterable<Tag<T>> getTags(String registry, Class<T> clazz) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
}
|
}
|
||||||
@ -1216,10 +1219,10 @@ public class FakeServer implements Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LootTable getLootTable(NamespacedKey arg0) {
|
public LootTable getLootTable(NamespacedKey arg0) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> selectEntities(CommandSender sender, String selector) throws IllegalArgumentException {
|
public List<Entity> selectEntities(CommandSender sender, String selector) throws IllegalArgumentException {
|
||||||
|
@ -21,5 +21,10 @@
|
|||||||
<artifactId>EssentialsX</artifactId>
|
<artifactId>EssentialsX</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.papermc</groupId>
|
||||||
|
<artifactId>paperlib</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
|
|||||||
import com.earth2me.essentials.textreader.IText;
|
import com.earth2me.essentials.textreader.IText;
|
||||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||||
import com.earth2me.essentials.textreader.SimpleTextPager;
|
import com.earth2me.essentials.textreader.SimpleTextPager;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
import net.ess3.api.IEssentials;
|
import net.ess3.api.IEssentials;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -74,8 +75,7 @@ class EssentialsSpawnPlayerListener implements Listener {
|
|||||||
ess.scheduleSyncDelayedTask(() -> {
|
ess.scheduleSyncDelayedTask(() -> {
|
||||||
Location spawn = spawns.getSpawn(user.getGroup());
|
Location spawn = spawns.getSpawn(user.getGroup());
|
||||||
try {
|
try {
|
||||||
// We don't use user.getTeleport() because it stores last location, which is unwanted in this case.
|
PaperLib.teleportAsync(user.getBase(), spawn, TeleportCause.PLUGIN);
|
||||||
user.getBase().teleport(spawn, TeleportCause.PLUGIN);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ess.showError(user.getSource(), e, "spawn-on-join");
|
ess.showError(user.getSource(), e, "spawn-on-join");
|
||||||
}
|
}
|
||||||
|
4
pom.xml
4
pom.xml
@ -31,6 +31,10 @@
|
|||||||
<id>bukkit-repo</id>
|
<id>bukkit-repo</id>
|
||||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>paper-repo</id>
|
||||||
|
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
Loading…
Reference in New Issue
Block a user