mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-07-03 22:24:43 +02:00
Compare commits
13 Commits
6.6.3
...
feature/v6
Author | SHA1 | Date | |
---|---|---|---|
6aa3f7c1b7 | |||
9f3507ea85 | |||
13d7357c85 | |||
16e26b910c | |||
faadebd30e | |||
2aeacb3dcf | |||
9db7791835 | |||
f49ddb819d | |||
d71c62771e | |||
a6aaa9538f | |||
0974fb2834 | |||
8982b33b6c | |||
a7b3b3b7df |
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
@ -26,12 +26,12 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v2
|
||||||
|
@ -80,7 +80,8 @@ final class DelegatePlotGenerator extends IndependentPlotGenerator {
|
|||||||
result.setBiome(x, z, BukkitAdapter.adapt(biome));
|
result.setBiome(x, z, BukkitAdapter.adapt(biome));
|
||||||
}
|
}
|
||||||
|
|
||||||
//do not annotate with Override until we discontinue support for 1.4.4
|
//do not annotate with Override until we discontinue support for 1.4.4 (we no longer support 1.4.4)
|
||||||
|
@Override
|
||||||
public void setBiome(int x, int y, int z, @NonNull Biome biome) {
|
public void setBiome(int x, int y, int z, @NonNull Biome biome) {
|
||||||
result.setBiome(x, z, BukkitAdapter.adapt(biome));
|
result.setBiome(x, z, BukkitAdapter.adapt(biome));
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ import com.plotsquared.core.player.PlotPlayer;
|
|||||||
import com.plotsquared.core.plot.Plot;
|
import com.plotsquared.core.plot.Plot;
|
||||||
import com.plotsquared.core.plot.PlotArea;
|
import com.plotsquared.core.plot.PlotArea;
|
||||||
import com.plotsquared.core.plot.flag.implementations.DoneFlag;
|
import com.plotsquared.core.plot.flag.implementations.DoneFlag;
|
||||||
|
import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
|
||||||
import com.plotsquared.core.plot.world.PlotAreaManager;
|
import com.plotsquared.core.plot.world.PlotAreaManager;
|
||||||
import com.plotsquared.core.util.Permissions;
|
import com.plotsquared.core.util.Permissions;
|
||||||
import net.kyori.adventure.text.minimessage.Template;
|
import net.kyori.adventure.text.minimessage.Template;
|
||||||
@ -352,13 +353,15 @@ public class PaperListener implements Listener {
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
} else if (!plot.isAdded(pp.getUUID())) {
|
} else if (!plot.isAdded(pp.getUUID())) {
|
||||||
if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
|
if (!plot.getFlag(ProjectilesFlag.class)) {
|
||||||
pp.sendMessage(
|
if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
|
||||||
TranslatableCaption.of("permission.no_permission_event"),
|
pp.sendMessage(
|
||||||
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER))
|
TranslatableCaption.of("permission.no_permission_event"),
|
||||||
);
|
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER))
|
||||||
entity.remove();
|
);
|
||||||
event.setCancelled(true);
|
entity.remove();
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import com.plotsquared.core.player.PlotPlayer;
|
|||||||
import com.plotsquared.core.plot.Plot;
|
import com.plotsquared.core.plot.Plot;
|
||||||
import com.plotsquared.core.plot.PlotArea;
|
import com.plotsquared.core.plot.PlotArea;
|
||||||
import com.plotsquared.core.plot.PlotHandler;
|
import com.plotsquared.core.plot.PlotHandler;
|
||||||
|
import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
|
||||||
import com.plotsquared.core.plot.world.PlotAreaManager;
|
import com.plotsquared.core.plot.world.PlotAreaManager;
|
||||||
import com.plotsquared.core.util.Permissions;
|
import com.plotsquared.core.util.Permissions;
|
||||||
import net.kyori.adventure.text.minimessage.Template;
|
import net.kyori.adventure.text.minimessage.Template;
|
||||||
@ -128,13 +129,15 @@ public class ProjectileEventListener implements Listener {
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
} else if (!plot.isAdded(pp.getUUID())) {
|
} else if (!plot.isAdded(pp.getUUID())) {
|
||||||
if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
|
if (!plot.getFlag(ProjectilesFlag.class)) {
|
||||||
pp.sendMessage(
|
if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
|
||||||
TranslatableCaption.of("permission.no_permission_event"),
|
pp.sendMessage(
|
||||||
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER))
|
TranslatableCaption.of("permission.no_permission_event"),
|
||||||
);
|
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER))
|
||||||
entity.remove();
|
);
|
||||||
event.setCancelled(true);
|
entity.remove();
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +165,7 @@ public class ProjectileEventListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (plot.isAdded(pp.getUUID()) || Permissions
|
if (plot.isAdded(pp.getUUID()) || Permissions
|
||||||
.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
|
.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER) || plot.getFlag(ProjectilesFlag.class)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entity.remove();
|
entity.remove();
|
||||||
|
@ -51,6 +51,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.Container;
|
import org.bukkit.block.Container;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
@ -266,7 +267,13 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
|||||||
} catch (WorldEditException ignored) {
|
} catch (WorldEditException ignored) {
|
||||||
// Fallback to not so nice method
|
// Fallback to not so nice method
|
||||||
BlockData blockData = BukkitAdapter.adapt(block);
|
BlockData blockData = BukkitAdapter.adapt(block);
|
||||||
Block existing = getBukkitWorld().getBlockAt(x, y, z);
|
Block existing;
|
||||||
|
// Assume a chunk object has been given only when it should have been.
|
||||||
|
if (getChunkObject() instanceof Chunk chunkObject) {
|
||||||
|
existing = chunkObject.getBlock(x & 15, y, z & 15);
|
||||||
|
} else {
|
||||||
|
existing = getBukkitWorld().getBlockAt(x, y, z);
|
||||||
|
}
|
||||||
final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData());
|
final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData());
|
||||||
if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData().matches(blockData)) {
|
if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData().matches(blockData)) {
|
||||||
return;
|
return;
|
||||||
|
@ -889,8 +889,8 @@ public class PlotSquared {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
LOGGER.info("| generator: {}>{}", baseGenerator, areaGen);
|
LOGGER.info("| generator: {}>{}", baseGenerator, areaGen);
|
||||||
LOGGER.info("| plot world: {}", pa);
|
LOGGER.info("| plot world: {}", pa.getClass().getCanonicalName());
|
||||||
LOGGER.info("| manager: {}", pa);
|
LOGGER.info("| manager: {}", pa.getPlotManager().getClass().getCanonicalName());
|
||||||
LOGGER.info("Note: Area created for cluster '{}' (invalid or old configuration?)", name);
|
LOGGER.info("Note: Area created for cluster '{}' (invalid or old configuration?)", name);
|
||||||
areaGen.getPlotGenerator().initialize(pa);
|
areaGen.getPlotGenerator().initialize(pa);
|
||||||
areaGen.augment(pa);
|
areaGen.augment(pa);
|
||||||
@ -906,6 +906,13 @@ public class PlotSquared {
|
|||||||
throw new IllegalArgumentException("Invalid Generator: " + gen_string);
|
throw new IllegalArgumentException("Invalid Generator: " + gen_string);
|
||||||
}
|
}
|
||||||
PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null);
|
PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null);
|
||||||
|
LOGGER.info("- generator: {}>{}", baseGenerator, areaGen);
|
||||||
|
LOGGER.info("- plot world: {}", pa.getClass().getCanonicalName());
|
||||||
|
LOGGER.info("- plot area manager: {}", pa.getPlotManager().getClass().getCanonicalName());
|
||||||
|
if (!this.worldConfiguration.contains(path)) {
|
||||||
|
this.worldConfiguration.createSection(path);
|
||||||
|
worldSection = this.worldConfiguration.getConfigurationSection(path);
|
||||||
|
}
|
||||||
pa.saveConfiguration(worldSection);
|
pa.saveConfiguration(worldSection);
|
||||||
pa.loadDefaultConfiguration(worldSection);
|
pa.loadDefaultConfiguration(worldSection);
|
||||||
try {
|
try {
|
||||||
@ -913,9 +920,6 @@ public class PlotSquared {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
LOGGER.info("- generator: {}>{}", baseGenerator, areaGen);
|
|
||||||
LOGGER.info("- plot world: {}", pa);
|
|
||||||
LOGGER.info("- plot area manager: {}", pa.getPlotManager());
|
|
||||||
areaGen.getPlotGenerator().initialize(pa);
|
areaGen.getPlotGenerator().initialize(pa);
|
||||||
areaGen.augment(pa);
|
areaGen.augment(pa);
|
||||||
addPlotArea(pa);
|
addPlotArea(pa);
|
||||||
|
@ -93,6 +93,7 @@ import com.plotsquared.core.plot.flag.implementations.PlayerInteractFlag;
|
|||||||
import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag;
|
import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag;
|
||||||
import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag;
|
import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag;
|
||||||
import com.plotsquared.core.plot.flag.implementations.PriceFlag;
|
import com.plotsquared.core.plot.flag.implementations.PriceFlag;
|
||||||
|
import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
|
||||||
import com.plotsquared.core.plot.flag.implementations.PveFlag;
|
import com.plotsquared.core.plot.flag.implementations.PveFlag;
|
||||||
import com.plotsquared.core.plot.flag.implementations.PvpFlag;
|
import com.plotsquared.core.plot.flag.implementations.PvpFlag;
|
||||||
import com.plotsquared.core.plot.flag.implementations.RedstoneFlag;
|
import com.plotsquared.core.plot.flag.implementations.RedstoneFlag;
|
||||||
@ -198,6 +199,7 @@ public final class GlobalFlagContainer extends FlagContainer {
|
|||||||
this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE);
|
this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE);
|
||||||
this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE);
|
this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE);
|
||||||
this.addFlag(VineGrowFlag.VINE_GROW_TRUE);
|
this.addFlag(VineGrowFlag.VINE_GROW_TRUE);
|
||||||
|
this.addFlag(ProjectilesFlag.PROJECTILES_FALSE);
|
||||||
|
|
||||||
// Double flags
|
// Double flags
|
||||||
this.addFlag(PriceFlag.PRICE_NOT_BUYABLE);
|
this.addFlag(PriceFlag.PRICE_NOT_BUYABLE);
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* _____ _ _ _____ _
|
||||||
|
* | __ \| | | | / ____| | |
|
||||||
|
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
|
||||||
|
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
|
||||||
|
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
|
||||||
|
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
|
||||||
|
* | |
|
||||||
|
* |_|
|
||||||
|
* PlotSquared plot management system for Minecraft
|
||||||
|
* Copyright (C) 2014 - 2022 IntellectualSites
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.plotsquared.core.plot.flag.implementations;
|
||||||
|
|
||||||
|
import com.plotsquared.core.configuration.caption.TranslatableCaption;
|
||||||
|
import com.plotsquared.core.plot.flag.types.BooleanFlag;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
public class ProjectilesFlag extends BooleanFlag<ProjectilesFlag> {
|
||||||
|
|
||||||
|
public static final ProjectilesFlag PROJECTILES_TRUE = new ProjectilesFlag(true);
|
||||||
|
public static final ProjectilesFlag PROJECTILES_FALSE = new ProjectilesFlag(false);
|
||||||
|
|
||||||
|
private ProjectilesFlag(boolean value){
|
||||||
|
super(value, TranslatableCaption.of("flags.flag_description_projectiles"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProjectilesFlag flagOf(@NonNull final Boolean value) {
|
||||||
|
return value ? PROJECTILES_TRUE : PROJECTILES_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -143,7 +143,8 @@ public abstract class QueueCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a chunk object (e.g. the Bukkit Chunk object) to the queue
|
* Set a chunk object (e.g. the Bukkit Chunk object) to the queue. This will be used as fallback in case of WNA failure.
|
||||||
|
* Should ONLY be used in specific cases (i.e. generation, where a chunk is being populated)
|
||||||
*
|
*
|
||||||
* @param chunkObject chunk object. Usually the implementation-specific chunk (e.g. bukkit Chunk)
|
* @param chunkObject chunk object. Usually the implementation-specific chunk (e.g. bukkit Chunk)
|
||||||
*/
|
*/
|
||||||
|
@ -409,13 +409,26 @@ public abstract class RegionManager {
|
|||||||
) {
|
) {
|
||||||
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
||||||
queue.addReadChunks(region.getChunks());
|
queue.addReadChunks(region.getChunks());
|
||||||
queue.setChunkConsumer(blockVector2 -> {
|
final BlockVector3 regionMin = region.getMinimumPoint();
|
||||||
|
final BlockVector3 regionMax = region.getMaximumPoint();
|
||||||
|
queue.setChunkConsumer(chunkPos -> {
|
||||||
|
BlockVector3 chunkMin = BlockVector3.at(
|
||||||
|
Math.max(chunkPos.getX() << 4, regionMin.getBlockX()),
|
||||||
|
regionMin.getBlockY(),
|
||||||
|
Math.max(chunkPos.getZ() << 4, regionMin.getBlockZ())
|
||||||
|
);
|
||||||
|
BlockVector3 chunkMax = BlockVector3.at(
|
||||||
|
Math.min((chunkPos.getX() << 4) + 15, regionMax.getBlockX()),
|
||||||
|
regionMax.getBlockY(),
|
||||||
|
Math.min((chunkPos.getZ() << 4) + 15, regionMax.getBlockZ())
|
||||||
|
);
|
||||||
|
CuboidRegion chunkRegion = new CuboidRegion(region.getWorld(), chunkMin, chunkMax);
|
||||||
WorldUtil.setBiome(
|
WorldUtil.setBiome(
|
||||||
area.getWorldName(),
|
area.getWorldName(),
|
||||||
region,
|
chunkRegion,
|
||||||
biome
|
biome
|
||||||
);
|
);
|
||||||
worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), area.getWorldName());
|
worldUtil.refreshChunk(chunkPos.getBlockX(), chunkPos.getBlockZ(), area.getWorldName());
|
||||||
});
|
});
|
||||||
queue.setCompleteTask(whenDone);
|
queue.setCompleteTask(whenDone);
|
||||||
queue.enqueue();
|
queue.enqueue();
|
||||||
|
@ -613,6 +613,7 @@
|
|||||||
"flags.flag_description_lectern_read_book": "<gray>Prevent players taking books from lecterns.</gray>",
|
"flags.flag_description_lectern_read_book": "<gray>Prevent players taking books from lecterns.</gray>",
|
||||||
"flags.flag_description_prevent_creative_copy": "<gray>Prevents people from copying item NBT data in the plot unless they're added as members.</gray>",
|
"flags.flag_description_prevent_creative_copy": "<gray>Prevents people from copying item NBT data in the plot unless they're added as members.</gray>",
|
||||||
"flags.flag_description_leaf_decay": "<gray>Set to `false` to prevent leaves from decaying.",
|
"flags.flag_description_leaf_decay": "<gray>Set to `false` to prevent leaves from decaying.",
|
||||||
|
"flags.flag_description_projectiles": "<gray>Prevents guests from shooting projectiles on the plot when set to false.</gray>",
|
||||||
"flags.flag_error_boolean": "Flag value must be a boolean (true | false).",
|
"flags.flag_error_boolean": "Flag value must be a boolean (true | false).",
|
||||||
"flags.flag_error_enum": "Must be one of: <list>",
|
"flags.flag_error_enum": "Must be one of: <list>",
|
||||||
"flags.flag_error_integer": "Flag value must be a whole positive number.",
|
"flags.flag_error_integer": "Flag value must be a whole positive number.",
|
||||||
|
@ -18,7 +18,7 @@ plugins {
|
|||||||
idea
|
idea
|
||||||
}
|
}
|
||||||
|
|
||||||
version = "6.6.3"
|
version = "6.7.1-SNAPSHOT"
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "com.plotsquared"
|
group = "com.plotsquared"
|
||||||
@ -140,7 +140,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
developer {
|
developer {
|
||||||
id.set("NotMyFault")
|
id.set("NotMyFault")
|
||||||
name.set("NotMyFault")
|
name.set("Alexander Brandes")
|
||||||
organization.set("IntellectualSites")
|
organization.set("IntellectualSites")
|
||||||
email.set("contact@notmyfault.dev")
|
email.set("contact@notmyfault.dev")
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ guava = "31.0.1-jre" # Version set by Minecraft
|
|||||||
|
|
||||||
# Platform expectations
|
# Platform expectations
|
||||||
paper = "1.18.1-R0.1-SNAPSHOT"
|
paper = "1.18.1-R0.1-SNAPSHOT"
|
||||||
checker-qual = "3.21.4"
|
checker-qual = "3.22.0"
|
||||||
guice = "5.1.0"
|
guice = "5.1.0"
|
||||||
spotbugs = "4.6.0"
|
spotbugs = "4.7.0"
|
||||||
snakeyaml = "1.30" # Version set by Bukkit
|
snakeyaml = "1.30" # Version set by Bukkit
|
||||||
|
|
||||||
# Adventure & MiniMessage
|
# Adventure & MiniMessage
|
||||||
@ -18,7 +18,7 @@ adventure-platform-bukkit = "4.0.1"
|
|||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
worldedit = "7.2.10"
|
worldedit = "7.2.10"
|
||||||
fawe = "2.1.1"
|
fawe = "2.1.2"
|
||||||
vault = "1.7.1"
|
vault = "1.7.1"
|
||||||
placeholderapi = "2.11.1"
|
placeholderapi = "2.11.1"
|
||||||
luckperms = "5.4"
|
luckperms = "5.4"
|
||||||
|
Reference in New Issue
Block a user