mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2026-11-04 17:10:11 -05:00
Compare commits
25
Commits
master
...
version/7.0.x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63e206713b | ||
|
|
488d94d640 | ||
|
|
da30a99320 | ||
|
|
a4e15295c2 | ||
|
|
1c98e6d5a1 | ||
|
|
d9a8ca5042 | ||
|
|
90acadb235 | ||
|
|
5c0c7b4781 | ||
|
|
5e8c7634b0 | ||
|
|
1dea00d293 | ||
|
|
cb77add3c9 | ||
|
|
9545cce43a | ||
|
|
0b6c3f1045 | ||
|
|
3f9b7cf4e0 | ||
|
|
fdbdb91816 | ||
|
|
a670fc70f9 | ||
|
|
408845ad09 | ||
|
|
96d18c4efc | ||
|
|
a468153cd8 | ||
|
|
4181ebfe36 | ||
|
|
a6d64dcc79 | ||
|
|
f395a1675b | ||
|
|
0aeb9d8d54 | ||
|
|
7c280a1348 | ||
|
|
c90c483862 |
No files matched your search
@@ -1,5 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## 7.0.21
|
||||
|
||||
* Improved protection checks for placing cushions.
|
||||
* Fixed straw beds not being treated as beds for certain flags.
|
||||
* Fixed cases where creepers could lose tracking of players who triggered them to explode.
|
||||
* Improved caching to ensure unloaded worlds are not kept around in memory longer than necessary.
|
||||
* Improved Folia detection to better detect Folia forks.
|
||||
* Fixed errors on Folia caused by complex cross-world block interactions.
|
||||
|
||||
## 7.0.20
|
||||
|
||||
* Require 26.3+.
|
||||
* Fixed poplar boats causing errors in some situations.
|
||||
* Support Paper's new EntityBreakEvent (used for cushion destruction) in protection.
|
||||
* Improved handling of buckets on waterlogged blocks when sneaking.
|
||||
* Fixed a Folia error caused by entity actions occurring across Folia region boundaries.
|
||||
* Improved command feedback when setting a state flag to "none".
|
||||
|
||||
## 7.0.19
|
||||
|
||||
* Require 26.2+.
|
||||
* Improved handling for TNT inside of sulfur cubes.
|
||||
* Improve performance of mob spawn prevention on Paper servers in some situations.
|
||||
* Improved handling of certain flags when `/wg flushstates` is run, or in certain login situations.
|
||||
|
||||
## 7.0.18
|
||||
|
||||
* Add lava-harden flag for cobblestone/stone/obsidian/basalt forming.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
group=com.sk89q.worldguard
|
||||
version=7.0.19-SNAPSHOT
|
||||
version=7.0.22-SNAPSHOT
|
||||
|
||||
org.gradle.parallel=true
|
||||
@@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
worldedit = "7.4.4"
|
||||
worldedit = "7.4.6"
|
||||
crankcase = "0.1.0"
|
||||
|
||||
# Minimum versions we apply to make dependencies support newer Java
|
||||
@@ -27,7 +27,7 @@ autoService = "com.google.auto.service:auto-service:1.1.1"
|
||||
jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
|
||||
jetbrains-annotations = "org.jetbrains:annotations:24.1.0"
|
||||
|
||||
paperApi = "io.papermc.paper:paper-api:26.2.build.+"
|
||||
paperApi = "io.papermc.paper:paper-api:26.3.build.+"
|
||||
paperLib = "io.papermc:paperlib:1.0.8"
|
||||
|
||||
dummypermscompat = "com.sk89q:dummypermscompat:1.10"
|
||||
|
||||
+2
-2
@@ -91,7 +91,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
|
||||
plugin.createDefaultConfiguration(configFile, "config_world.yml");
|
||||
plugin.createDefaultConfiguration(blacklistFile, "blacklist.txt");
|
||||
|
||||
config = new YAMLProcessor(configFile, true, YAMLFormat.EXTENDED);
|
||||
config = new YAMLProcessor(configFile.toPath(), true, YAMLFormat.EXTENDED);
|
||||
loadConfiguration();
|
||||
|
||||
if (summaryOnStart) {
|
||||
@@ -298,7 +298,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
|
||||
explosionFlagCancellation = getBoolean("regions.explosion-flags-block-entity-damage", true);
|
||||
highFreqFlags = getBoolean("regions.high-frequency-flags", false);
|
||||
checkLiquidFlow = getBoolean("regions.protect-against-liquid-flow", false);
|
||||
regionWand = convertLegacyItem(getString("regions.wand", ItemTypes.LEATHER.getId()));
|
||||
regionWand = convertLegacyItem(getString("regions.wand", ItemTypes.LEATHER.id()));
|
||||
maxClaimVolume = getInt("regions.max-claim-volume", 30000);
|
||||
claimOnlyInsideExistingRegions = getBoolean("regions.claim-only-inside-existing-regions", false);
|
||||
setParentOnClaim = getString("regions.set-parent-on-claim", "");
|
||||
|
||||
@@ -559,15 +559,14 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
|
||||
private final LazyReference<Boolean> folia = LazyReference.from(() -> {
|
||||
try {
|
||||
// Folia is Paper-based, so this is a good first check.
|
||||
if (PaperLib.isPaper()) {
|
||||
return ServerBuildInfo.buildInfo().isBrandCompatible(net.kyori.adventure.key.Key.key("papermc", "folia"));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return getWorldEdit().isFolia(); // Delegate check to WorldEdit
|
||||
} catch (NoSuchMethodError _) {
|
||||
// Ignore, this likely means an outdated version.
|
||||
LOGGER.warn("Failed to check if server is running Folia, as WorldEdit's Folia support is missing.");
|
||||
} catch (Throwable t) {
|
||||
// Unknown error, log it and return false.
|
||||
LOGGER.warn("Failed to check if server is running Folia", t);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.LightningStrike;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.SulfurCube;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
@@ -117,7 +118,7 @@ public final class Cause {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (object instanceof TNTPrimed || object instanceof Vehicle) {
|
||||
if (object instanceof TNTPrimed || object instanceof Vehicle || object instanceof SulfurCube) {
|
||||
if (!PaperLib.isPaper()) {
|
||||
return false;
|
||||
}
|
||||
@@ -178,7 +179,8 @@ public final class Cause {
|
||||
@Nullable
|
||||
public Block getFirstBlock() {
|
||||
for (Object object : causes) {
|
||||
if (object instanceof Block b) {
|
||||
if (object instanceof Block b && (!WorldGuardPlugin.inst().isFolia()
|
||||
|| Bukkit.isOwnedByCurrentRegion(b.getLocation()))) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
@@ -330,10 +332,16 @@ public final class Cause {
|
||||
}
|
||||
} else if (o instanceof Creeper c) {
|
||||
indirect = true;
|
||||
addAll(c.getTarget(), c.getIgniter());
|
||||
if (!WorldGuardPlugin.inst().isFolia()
|
||||
|| Bukkit.isOwnedByCurrentRegion(c)) {
|
||||
addAll(c.getTarget(), c.getIgniter());
|
||||
}
|
||||
} else if (o instanceof Creature c) {
|
||||
indirect = true;
|
||||
addAll(c.getTarget());
|
||||
if (!WorldGuardPlugin.inst().isFolia()
|
||||
|| Bukkit.isOwnedByCurrentRegion(c)) {
|
||||
addAll(c.getTarget());
|
||||
}
|
||||
} else if (o instanceof BlockProjectileSource) {
|
||||
addAll(((BlockProjectileSource) o).getBlock());
|
||||
} else if (o instanceof LightningStrike && PaperLib.isPaper() &&
|
||||
|
||||
+57
-5
@@ -48,6 +48,8 @@ import com.sk89q.worldguard.bukkit.util.PaperInterop;
|
||||
import com.sk89q.worldguard.config.WorldConfiguration;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.paper.event.entity.EntityBreakByEntityEvent;
|
||||
import io.papermc.paper.event.entity.EntityBreakEvent;
|
||||
import io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent;
|
||||
import io.papermc.paper.event.player.PlayerOpenSignEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -77,12 +79,14 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.FishHook;
|
||||
import org.bukkit.entity.Hanging;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.entity.Painting;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.SulfurCube;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.ThrownPotion;
|
||||
import org.bukkit.entity.WindCharge;
|
||||
@@ -242,7 +246,7 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
BlockState previousState = event.getBlockReplacedState();
|
||||
|
||||
// Some blocks, like tall grass and fire, get replaced
|
||||
if (previousState.getType() != Material.AIR && previousState.getType() != event.getBlockReplacedState().getType()) {
|
||||
if (previousState.getType() != Material.AIR && previousState.getType() != event.getBlockPlaced().getType()) {
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), previousState.getLocation(), previousState.getType()));
|
||||
}
|
||||
|
||||
@@ -667,8 +671,13 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
Player player = event.getPlayer();
|
||||
Block blockClicked = event.getBlockClicked();
|
||||
Block blockAffected;
|
||||
|
||||
if (blockClicked.getBlockData() instanceof Waterlogged) {
|
||||
boolean canPlaceInside = false;
|
||||
// Can be placed inside blocks only when not sneaking
|
||||
if (!player.isSneaking()) {
|
||||
canPlaceInside = (event.getBucket() != Material.LAVA_BUCKET && blockClicked.getBlockData() instanceof Waterlogged)
|
||||
|| (Materials.isCauldron(blockClicked.getType()) && Materials.isCauldronBucketType(event.getBucket()));
|
||||
}
|
||||
if (canPlaceInside) {
|
||||
blockAffected = blockClicked;
|
||||
} else {
|
||||
blockAffected = blockClicked.getRelative(event.getBlockFace());
|
||||
@@ -895,7 +904,18 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
if (matchingItem != null && hasInteractBypass(world, matchingItem)) {
|
||||
useEntityEvent.setAllowed(true);
|
||||
}
|
||||
Events.fireToCancel(event, useEntityEvent);
|
||||
if (!Events.fireToCancel(event, useEntityEvent)) {
|
||||
/* Sulfur cube doesn't have API for interaction/ignition source tracking */
|
||||
if(entity instanceof SulfurCube) {
|
||||
/* Remove player in case of using shears */
|
||||
if(item.getType() == Material.SHEARS) {
|
||||
Cause.untrackParentCause(entity);
|
||||
/* Save player overwise */
|
||||
} else {
|
||||
Cause.trackParentCause(entity, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@@ -917,6 +937,8 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
eventToFire.getRelevantFlags().add(Flags.FIREWORK_DAMAGE);
|
||||
} else if (damager instanceof Creeper) {
|
||||
eventToFire.getRelevantFlags().add(Flags.CREEPER_EXPLOSION);
|
||||
} else if (damager instanceof SulfurCube) {
|
||||
eventToFire.getRelevantFlags().add(Flags.TNT);
|
||||
}
|
||||
if (Events.fireToCancel(event, eventToFire)) {
|
||||
if (damager instanceof Tameable && damager instanceof Mob) {
|
||||
@@ -1244,7 +1266,17 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
|
||||
// Handle created boats
|
||||
if (item != null && Materials.isBoat(item.getType())) {
|
||||
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), Materials.getRelatedEntity(item.getType())));
|
||||
EntityType entityType = Materials.getRelatedEntity(item.getType());
|
||||
if (entityType == null) {
|
||||
entityType = EntityType.OAK_BOAT;
|
||||
}
|
||||
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), entityType));
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle created cushions
|
||||
if (item != null && Materials.isCushion(item.getType())) {
|
||||
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.CUSHION));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1362,6 +1394,26 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
public void onEntityKnockbackByEntity(EntityPushedByEntityAttackEvent event) {
|
||||
handleKnockback(event, event.getPushedBy());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityBreak(EntityBreakEvent event) {
|
||||
if (event.getEntity() instanceof Hanging) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event instanceof EntityBreakByEntityEvent entityEvent) {
|
||||
Entity remover = entityEvent.getRemover();
|
||||
Events.fireToCancel(event, new DestroyEntityEvent(event, create(remover), event.getEntity()));
|
||||
|
||||
if (event.isCancelled() && remover instanceof Player player) {
|
||||
playDenyEffect(player, event.getEntity().getLocation());
|
||||
}
|
||||
} else if (event.getCause() == EntityBreakEvent.RemoveCause.EXPLOSION) {
|
||||
DestroyEntityEvent destroyEntityEvent = new DestroyEntityEvent(event, Cause.unknown(), event.getEntity());
|
||||
destroyEntityEvent.getRelevantFlags().add(Flags.OTHER_EXPLOSION);
|
||||
Events.fireToCancel(event, destroyEntityEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
|
||||
+2
-1
@@ -57,6 +57,7 @@ import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.SulfurCube;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.Event.Result;
|
||||
@@ -222,7 +223,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
String what;
|
||||
|
||||
/* TNT */
|
||||
if (event.getCause().find(EntityType.TNT, EntityType.TNT_MINECART) != null) {
|
||||
if (event.getCause().find(EntityType.TNT, EntityType.TNT_MINECART, EntityType.SULFUR_CUBE) != null) {
|
||||
canBreak = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.BLOCK_BREAK, Flags.TNT));
|
||||
what = "use dynamite";
|
||||
|
||||
|
||||
+9
-9
@@ -154,7 +154,7 @@ public class WorldGuardBlockListener extends AbstractListener {
|
||||
Material targetId = blockTo.getType();
|
||||
|
||||
if ((isAir || isWater) &&
|
||||
wcfg.preventWaterDamage.contains(BukkitAdapter.asBlockType(targetId).getId())) {
|
||||
wcfg.preventWaterDamage.contains(BukkitAdapter.asBlockType(targetId).id())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public class WorldGuardBlockListener extends AbstractListener {
|
||||
if (!wcfg.allowedLavaSpreadOver.isEmpty() && isLava) {
|
||||
Material targetId = blockTo.getRelative(0, -1, 0).getType();
|
||||
|
||||
if (!wcfg.allowedLavaSpreadOver.contains(BukkitAdapter.asBlockType(targetId).getId())) {
|
||||
if (!wcfg.allowedLavaSpreadOver.contains(BukkitAdapter.asBlockType(targetId).id())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@@ -233,11 +233,11 @@ public class WorldGuardBlockListener extends AbstractListener {
|
||||
int y = block.getY();
|
||||
int z = block.getZ();
|
||||
|
||||
if (wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x, y - 1, z).getType()).getId())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x + 1, y, z).getType()).getId())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x - 1, y, z).getType()).getId())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x, y, z - 1).getType()).getId())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x, y, z + 1).getType()).getId())) {
|
||||
if (wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x, y - 1, z).getType()).id())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x + 1, y, z).getType()).id())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x - 1, y, z).getType()).id())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x, y, z - 1).getType()).id())
|
||||
|| wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(world.getBlockAt(x, y, z + 1).getType()).id())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@@ -303,7 +303,7 @@ public class WorldGuardBlockListener extends AbstractListener {
|
||||
if (!wcfg.disableFireSpreadBlocks.isEmpty()) {
|
||||
Block block = event.getBlock();
|
||||
|
||||
if (wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(block.getType()).getId())) {
|
||||
if (wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(block.getType()).id())) {
|
||||
event.setCancelled(true);
|
||||
checkAndDestroyFireAround(block.getWorld(), block.getX(), block.getY(), block.getZ());
|
||||
return;
|
||||
@@ -511,7 +511,7 @@ public class WorldGuardBlockListener extends AbstractListener {
|
||||
if (!wcfg.allowedSnowFallOver.isEmpty()) {
|
||||
Material targetId = event.getBlock().getRelative(0, -1, 0).getType();
|
||||
|
||||
if (!wcfg.allowedSnowFallOver.contains(BukkitAdapter.asBlockType(targetId).getId())) {
|
||||
if (!wcfg.allowedSnowFallOver.contains(BukkitAdapter.asBlockType(targetId).id())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
+62
-8
@@ -20,6 +20,7 @@
|
||||
package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityZapEvent;
|
||||
import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
@@ -61,6 +62,7 @@ import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.SulfurCube;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.WindCharge;
|
||||
@@ -487,7 +489,7 @@ public class WorldGuardEntityListener extends AbstractListener {
|
||||
event.blockList().clear();
|
||||
return;
|
||||
}
|
||||
} else if (ent instanceof TNTPrimed || ent instanceof ExplosiveMinecart) {
|
||||
} else if (ent instanceof TNTPrimed || ent instanceof ExplosiveMinecart || ent instanceof SulfurCube) {
|
||||
if (wcfg.blockTNTExplosions) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
@@ -614,8 +616,12 @@ public class WorldGuardEntityListener extends AbstractListener {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (ent instanceof Creeper creeper && creeper.getTarget() instanceof Player player) {
|
||||
Cause.trackParentCause(creeper, player);
|
||||
}
|
||||
} else if (event.getEntityType() == EntityType.TNT
|
||||
|| event.getEntityType() == EntityType.TNT_MINECART) {
|
||||
|| event.getEntityType() == EntityType.TNT_MINECART
|
||||
|| event.getEntityType() == EntityType.SULFUR_CUBE) {
|
||||
if (wcfg.blockTNTExplosions) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
@@ -655,8 +661,11 @@ public class WorldGuardEntityListener extends AbstractListener {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityType entityType = event.getEntityType();
|
||||
handleCreatureSpawn(event, event.getLocation(), event.getEntityType(), event.getSpawnReason(), cfg, wcfg);
|
||||
}
|
||||
|
||||
private static void handleCreatureSpawn(Cancellable event, Location location, EntityType entityType, SpawnReason spawnReason,
|
||||
ConfigurationManager cfg, WorldConfiguration wcfg) {
|
||||
com.sk89q.worldedit.world.entity.EntityType weEntityType = BukkitAdapter.adapt(entityType);
|
||||
|
||||
if (weEntityType != null && wcfg.blockCreatureSpawn.contains(weEntityType)) {
|
||||
@@ -664,11 +673,9 @@ public class WorldGuardEntityListener extends AbstractListener {
|
||||
return;
|
||||
}
|
||||
|
||||
Location eventLoc = event.getLocation();
|
||||
|
||||
if (wcfg.useRegions && cfg.useRegionsCreatureSpawnEvent) {
|
||||
ApplicableRegionSet set =
|
||||
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(eventLoc));
|
||||
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(location));
|
||||
|
||||
if (!set.testState(null, Flags.MOB_SPAWNING)) {
|
||||
event.setCancelled(true);
|
||||
@@ -683,8 +690,8 @@ public class WorldGuardEntityListener extends AbstractListener {
|
||||
}
|
||||
|
||||
if (wcfg.blockGroundSlimes && entityType == EntityType.SLIME
|
||||
&& eventLoc.getY() >= 60
|
||||
&& event.getSpawnReason() == SpawnReason.NATURAL) {
|
||||
&& location.getY() >= 60
|
||||
&& spawnReason == SpawnReason.NATURAL) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@@ -905,6 +912,53 @@ public class WorldGuardEntityListener extends AbstractListener {
|
||||
handlePigZap(event.getEntity(), event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the natural spawn checks from {@link WorldGuardEntityListener#onCreatureSpawn} before the
|
||||
* server constructs the entity. The CreatureSpawnEvent checks fire at the very
|
||||
* end of the spawn pipeline, after the position was picked, the placement
|
||||
* checks ran and the mob was constructed and finalized, so a region that denies
|
||||
* mob spawning pays for a mob to be built and thrown away on every attempt.
|
||||
* Cancelling here skips the placement checks, the construction and
|
||||
* finalizeSpawn for a spawn that was going to be refused anyway.
|
||||
*
|
||||
* Cancelling does not end the chunk's remaining attempts. Only
|
||||
* setShouldAbortSpawn(true) makes the spawner return early; a plain cancel
|
||||
* falls through to the next candidate position exactly like a failed
|
||||
* placement check.
|
||||
*
|
||||
* Note that Paper fires this event for every candidate position, before the
|
||||
* light, block and collision checks, so the region query below runs
|
||||
* considerably more often than the CreatureSpawnEvent one did. On Paper with
|
||||
* per-player-mob-spawns enabled, which is the default, every cancelled pre
|
||||
* spawn is also charged to a per player mob backoff counter that is added to
|
||||
* the mob cap of every player within tick view distance and bleeds off one per
|
||||
* spawn cycle, so a large denied region can suppress spawning in neighbouring
|
||||
* chunks that allow mobs.
|
||||
*
|
||||
* Only NATURAL spawns are handled here; every other spawn reason keeps going
|
||||
* through the CreatureSpawnEvent checks unchanged.
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPreCreatureSpawn(PreCreatureSpawnEvent event) {
|
||||
if (event.getReason() != SpawnReason.NATURAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationManager cfg = getConfig();
|
||||
|
||||
if (!cfg.useRegionsPreCreatureSpawnEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cfg.activityHaltToggle) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Location spawnLoc = event.getSpawnLocation();
|
||||
handleCreatureSpawn(event, spawnLoc, event.getType(), event.getReason(), cfg, getWorldConfig(spawnLoc.getWorld()));
|
||||
}
|
||||
}
|
||||
|
||||
private static class SpigotListener implements Listener {
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ public class WorldGuardWeatherListener extends AbstractListener {
|
||||
if (targetId == Material.AIR) {
|
||||
targetId = target.getRelative(BlockFace.DOWN).getType();
|
||||
}
|
||||
if (wcfg.disallowedLightningBlocks.contains(BukkitAdapter.asBlockType(targetId).getId())) {
|
||||
if (wcfg.disallowedLightningBlocks.contains(BukkitAdapter.asBlockType(targetId).id())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.time.Duration;
|
||||
|
||||
public class EventDebounce<K> {
|
||||
|
||||
@@ -36,7 +36,7 @@ public class EventDebounce<K> {
|
||||
public EventDebounce(int debounceTime) {
|
||||
cache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterWrite(debounceTime, TimeUnit.MILLISECONDS)
|
||||
.expireAfterWrite(Duration.ofMillis(debounceTime))
|
||||
.concurrencyLevel(2)
|
||||
.build(new CacheLoader<K, Entry>() {
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.time.Duration;
|
||||
|
||||
public class AbstractEventDebounce<K> {
|
||||
|
||||
@@ -36,7 +36,7 @@ public class AbstractEventDebounce<K> {
|
||||
AbstractEventDebounce(int debounceTime) {
|
||||
cache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterWrite(debounceTime, TimeUnit.MILLISECONDS)
|
||||
.expireAfterWrite(Duration.ofMillis(debounceTime))
|
||||
.concurrencyLevel(2)
|
||||
.build(new CacheLoader<K, Entry>() {
|
||||
@Override
|
||||
|
||||
+9
-4
@@ -43,8 +43,8 @@ import java.util.function.Consumer;
|
||||
public class BukkitSessionManager extends AbstractSessionManager implements Runnable, Listener {
|
||||
|
||||
/**
|
||||
* Re-initialize handlers and clear "last position," "last state," etc.
|
||||
* information for all players.
|
||||
* Restore handler-managed state, re-initialize handlers, and clear
|
||||
* "last position," "last state," etc. information for all players.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@@ -72,9 +72,14 @@ public class BukkitSessionManager extends AbstractSessionManager implements Runn
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerProcess(ProcessPlayerEvent event) {
|
||||
// Pre-load a session
|
||||
// Create a new session or re-initialize a cached one.
|
||||
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer(event.getPlayer());
|
||||
get(player).initialize(player);
|
||||
Session session = getIfPresent(player);
|
||||
if (session == null) {
|
||||
get(player); // this also initializes the new session
|
||||
} else {
|
||||
session.resetState(player); // old sessions need explicit re-initialization
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.SpectralArrow;
|
||||
import org.bukkit.entity.Steerable;
|
||||
import org.bukkit.entity.SulfurCube;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
@@ -78,7 +79,9 @@ public final class Entities {
|
||||
* @return true if TNT based
|
||||
*/
|
||||
public static boolean isTNTBased(Entity entity) {
|
||||
return entity instanceof TNTPrimed || entity instanceof ExplosiveMinecart;
|
||||
return entity instanceof TNTPrimed
|
||||
|| entity instanceof ExplosiveMinecart
|
||||
|| entity instanceof SulfurCube sulfurCube && sulfurCube.canExplode();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,6 +268,7 @@ public final class Entities {
|
||||
case Wither wither -> Flags.WITHER_DAMAGE;
|
||||
case Creeper creeper -> Flags.CREEPER_EXPLOSION;
|
||||
case TNTPrimed tnt -> Flags.TNT;
|
||||
case SulfurCube sulfurCube -> Flags.TNT;
|
||||
case ExplosiveMinecart minecart -> Flags.TNT;
|
||||
case EnderDragon dragon -> Flags.ENDERDRAGON_BLOCK_DAMAGE;
|
||||
case null, default -> Flags.OTHER_EXPLOSION;
|
||||
|
||||
@@ -80,15 +80,15 @@ public final class Materials {
|
||||
ENTITY_ITEMS.put(EntityType.EGG, Material.EGG);
|
||||
ENTITY_ITEMS.put(EntityType.ARMOR_STAND, Material.ARMOR_STAND);
|
||||
ENTITY_ITEMS.put(EntityType.END_CRYSTAL, Material.END_CRYSTAL);
|
||||
ENTITY_ITEMS.put(EntityType.CUSHION, Material.WHITE_CUSHION);
|
||||
|
||||
for (String wood : new String[]{"OAK", "SPRUCE", "BIRCH", "JUNGLE", "ACACIA", "DARK_OAK", "MANGROVE", "CHERRY", "PALE_OAK"}) {
|
||||
String regular = wood + "_BOAT";
|
||||
String chest = wood + "_CHEST_BOAT";
|
||||
ENTITY_ITEMS.put(EntityType.valueOf(regular), Material.getMaterial(regular));
|
||||
ENTITY_ITEMS.put(EntityType.valueOf(chest), Material.getMaterial(chest));
|
||||
}
|
||||
ENTITY_ITEMS.put(EntityType.BAMBOO_RAFT, Material.BAMBOO_RAFT);
|
||||
ENTITY_ITEMS.put(EntityType.BAMBOO_CHEST_RAFT, Material.BAMBOO_CHEST_RAFT);
|
||||
// All boat items should have an entity equivalent, so we can use the tag to map them out.
|
||||
Tag.ITEMS_BOATS.getValues().forEach(mat -> {
|
||||
EntityType entityEquivalent = Registry.ENTITY_TYPE.get(mat.getKey());
|
||||
if (entityEquivalent != null) {
|
||||
ENTITY_ITEMS.put(entityEquivalent, mat);
|
||||
}
|
||||
});
|
||||
|
||||
// preset some tags to a default value, override some of them:
|
||||
putMaterialTag(Tag.DOORS, MODIFIED_ON_RIGHT);
|
||||
@@ -489,6 +489,7 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.SUGAR, 0);
|
||||
MATERIAL_FLAGS.put(Material.COOKIE, 0);
|
||||
MATERIAL_FLAGS.put(Material.MAP, 0);
|
||||
putMaterialTag(Tag.ITEMS_CLONABLE_MAPS, 0);
|
||||
MATERIAL_FLAGS.put(Material.SHEARS, 0);
|
||||
MATERIAL_FLAGS.put(Material.MELON_SLICE, 0);
|
||||
MATERIAL_FLAGS.put(Material.PUMPKIN_SEEDS, 0);
|
||||
@@ -602,6 +603,7 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.TRIDENT, 0);
|
||||
MATERIAL_FLAGS.put(Material.TROPICAL_FISH, 0);
|
||||
MATERIAL_FLAGS.put(Material.TROPICAL_FISH_BUCKET, 0);
|
||||
MATERIAL_FLAGS.put(Material.SULFUR_CUBE_BUCKET, 0);
|
||||
|
||||
MATERIAL_FLAGS.put(Material.CREEPER_BANNER_PATTERN, 0);
|
||||
MATERIAL_FLAGS.put(Material.FLOWER_BANNER_PATTERN, 0);
|
||||
@@ -747,6 +749,7 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.MOSS_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.HANGING_ROOTS, 0);
|
||||
MATERIAL_FLAGS.put(Material.POINTED_DRIPSTONE, 0);
|
||||
MATERIAL_FLAGS.put(Material.DRIPSTONE_BLOCK, 0);
|
||||
|
||||
// 1.19
|
||||
MATERIAL_FLAGS.put(Material.MUD, 0);
|
||||
@@ -948,6 +951,12 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.CHISELED_SULFUR, 0);
|
||||
putMaterialTag(Tag.SPELEOTHEMS, 0);
|
||||
|
||||
// 26.3
|
||||
MATERIAL_FLAGS.put(Material.RED_SHRUB, 0);
|
||||
MATERIAL_FLAGS.put(Material.STRAW_BED, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.SHELF_MUSHROOM, 0);
|
||||
putMaterialTag(Tag.ITEMS_CUSHIONS, 0);
|
||||
|
||||
Stream.concat(Stream.concat(
|
||||
Tag.CORAL_BLOCKS.getValues().stream(),
|
||||
Tag.CORALS.getValues().stream()),
|
||||
@@ -1058,6 +1067,7 @@ public final class Materials {
|
||||
return switch (type) {
|
||||
case LAVA_BUCKET -> Material.LAVA;
|
||||
case WATER_BUCKET -> Material.WATER;
|
||||
case POWDER_SNOW_BUCKET -> Material.POWDER_SNOW;
|
||||
default -> Material.WATER;
|
||||
};
|
||||
}
|
||||
@@ -1171,6 +1181,16 @@ public final class Materials {
|
||||
return Tag.ITEMS_BOATS.isTagged(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the given material is a Cushion.
|
||||
*
|
||||
* @param material the material
|
||||
* @return true if a Cushion item
|
||||
*/
|
||||
public static boolean isCushion(Material material) {
|
||||
return Tag.ITEMS_CUSHIONS.isTagged(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the given material is a Shulker Box.
|
||||
*
|
||||
@@ -1307,7 +1327,7 @@ public final class Materials {
|
||||
}
|
||||
|
||||
public static boolean isBed(Material material) {
|
||||
return Tag.BEDS.isTagged(material);
|
||||
return Tag.BEDS.isTagged(material) || material == Material.STRAW_BED;
|
||||
}
|
||||
|
||||
public static boolean isAnvil(Material material) {
|
||||
@@ -1584,4 +1604,19 @@ public final class Materials {
|
||||
public static boolean isSculkGrowth(Material mat) {
|
||||
return mat == Material.SCULK || mat == Material.SCULK_VEIN;
|
||||
}
|
||||
|
||||
public static boolean isCauldron(Material mat) {
|
||||
return switch (mat) {
|
||||
case CAULDRON, LAVA_CAULDRON, POWDER_SNOW_CAULDRON, WATER_CAULDRON -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
// Other buckets containing mobs cannot be placed inside cauldrons
|
||||
public static boolean isCauldronBucketType(Material mat) {
|
||||
return switch (mat) {
|
||||
case WATER_BUCKET, LAVA_BUCKET, POWDER_SNOW_BUCKET -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,5 @@ name: WorldGuard
|
||||
main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
|
||||
version: "${internalVersion}"
|
||||
depend: [WorldEdit]
|
||||
api-version: "26.2"
|
||||
api-version: "26.3"
|
||||
folia-supported: true
|
||||
@@ -37,9 +37,9 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class Blacklist {
|
||||
private boolean useAsWhitelist;
|
||||
private LoadingCache<String, TrackedEvent> repeatingEventCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.expireAfterAccess(Duration.ofSeconds(30))
|
||||
.build(CacheLoader.from(TrackedEvent::new));
|
||||
|
||||
public Blacklist(boolean useAsWhitelist) {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class BlockMatcher implements TargetMatcher {
|
||||
|
||||
@Override
|
||||
public String getMatchedTypeId() {
|
||||
return this.type.getId();
|
||||
return this.type.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class ItemBlockMatcher implements TargetMatcher {
|
||||
|
||||
@Override
|
||||
public String getMatchedTypeId() {
|
||||
return this.type.getId();
|
||||
return this.type.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class ItemMatcher implements TargetMatcher {
|
||||
|
||||
@Override
|
||||
public String getMatchedTypeId() {
|
||||
return this.type.getId();
|
||||
return this.type.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-1
@@ -597,11 +597,14 @@ public final class RegionCommands extends RegionCommandsBase {
|
||||
if (value != null) {
|
||||
// Set the flag if [value] was given even if [-g group] was given as well
|
||||
try {
|
||||
value = setFlag(existing, foundFlag, sender, value).toString();
|
||||
Object parsedValue = setFlag(existing, foundFlag, sender, value);
|
||||
value = parsedValue == null ? null : parsedValue.toString();
|
||||
} catch (InvalidFlagFormat e) {
|
||||
throw new CommandException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
if (!args.hasFlag('h')) {
|
||||
sender.print("Region flag " + foundFlag.getName() + " set on '" + regionId + "' to '" + value + "'.");
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ public abstract class ConfigurationManager {
|
||||
"#\r\n";
|
||||
|
||||
public boolean useRegionsCreatureSpawnEvent;
|
||||
public boolean useRegionsPreCreatureSpawnEvent;
|
||||
public boolean activityHaltToggle = false;
|
||||
public boolean useGodPermission;
|
||||
public boolean useGodGroup;
|
||||
|
||||
@@ -212,13 +212,13 @@ public abstract class WorldConfiguration {
|
||||
}
|
||||
ItemType legacyItem = LegacyMapper.getInstance().getItemFromLegacy(id, data);
|
||||
if (legacyItem != null) {
|
||||
return legacyItem.getId();
|
||||
return legacyItem.id();
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
final ItemType itemType = ItemTypes.get(legacy);
|
||||
if (itemType != null) {
|
||||
return itemType.getId();
|
||||
return itemType.id();
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -242,13 +242,13 @@ public abstract class WorldConfiguration {
|
||||
}
|
||||
BlockState legacyBlock = LegacyMapper.getInstance().getBlockFromLegacy(id, data);
|
||||
if (legacyBlock != null) {
|
||||
return legacyBlock.getBlockType().getId();
|
||||
return legacyBlock.getBlockType().id();
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
final BlockType blockType = BlockTypes.get(legacy);
|
||||
if (blockType != null) {
|
||||
return blockType.getId();
|
||||
return blockType.id();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+2
-1
@@ -44,7 +44,7 @@ public abstract class YamlConfigurationManager extends ConfigurationManager {
|
||||
public void load() {
|
||||
copyDefaults();
|
||||
|
||||
config = new YAMLProcessor(new File(getDataFolder(), "config.yml"), true, YAMLFormat.EXTENDED);
|
||||
config = new YAMLProcessor(new File(getDataFolder(), "config.yml").toPath(), true, YAMLFormat.EXTENDED);
|
||||
try {
|
||||
config.load();
|
||||
} catch (IOException e) {
|
||||
@@ -56,6 +56,7 @@ public abstract class YamlConfigurationManager extends ConfigurationManager {
|
||||
migrateRegionsToUuid = config.getBoolean("regions.uuid-migration.perform-on-next-start", true);
|
||||
keepUnresolvedNames = config.getBoolean("regions.uuid-migration.keep-names-that-lack-uuids", true);
|
||||
useRegionsCreatureSpawnEvent = config.getBoolean("regions.use-creature-spawn-event", true);
|
||||
useRegionsPreCreatureSpawnEvent = config.getBoolean("regions.use-pre-creature-spawn-event", false);
|
||||
disableDefaultBypass = config.getBoolean("regions.disable-bypass-by-default", false);
|
||||
announceBypassStatus = config.getBoolean("regions.announce-bypass-status", false);
|
||||
|
||||
|
||||
+1
-1
@@ -333,7 +333,7 @@ public class YamlRegionFile implements RegionDatabase {
|
||||
*/
|
||||
private YAMLProcessor createYamlProcessor(File file) {
|
||||
checkNotNull(file);
|
||||
return new YAMLProcessor(file, false, YAMLFormat.COMPACT);
|
||||
return new YAMLProcessor(file.toPath(), false, YAMLFormat.COMPACT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+17
-42
@@ -21,8 +21,6 @@ package com.sk89q.worldguard.session;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
@@ -43,12 +41,11 @@ import com.sk89q.worldguard.session.handler.WaterBreathing;
|
||||
import com.sk89q.worldguard.session.handler.WeatherLockFlag;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -59,21 +56,19 @@ public abstract class AbstractSessionManager implements SessionManager {
|
||||
public static final int RUN_DELAY = 20;
|
||||
public static final long SESSION_LIFETIME = 10;
|
||||
|
||||
private static final BiPredicate<World, LocalPlayer> BYPASS_PERMISSION_TEST = (world, player) -> {
|
||||
return player.hasPermission("worldguard.region.bypass." + world.getName());
|
||||
};
|
||||
private static final BiPredicate<World, LocalPlayer> BYPASS_PERMISSION_TEST = (world, player) -> player.hasPermission("worldguard.region.bypass." + world.getName());
|
||||
|
||||
private final LoadingCache<WorldPlayerTuple, Boolean> bypassCache = CacheBuilder.newBuilder()
|
||||
private final Cache<BypassCacheKey, Boolean> bypassCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterWrite(2, TimeUnit.SECONDS)
|
||||
.build(CacheLoader.from(tuple -> BYPASS_PERMISSION_TEST.test(tuple.getWorld(), tuple.getPlayer())));
|
||||
.expireAfterWrite(Duration.ofSeconds(2))
|
||||
.build();
|
||||
|
||||
private final Cache<CacheKey, Session> sessions = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(SESSION_LIFETIME, TimeUnit.MINUTES)
|
||||
private final Cache<UUID, Session> sessions = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(Duration.ofMinutes(SESSION_LIFETIME))
|
||||
.build();
|
||||
|
||||
private boolean hasCustom = false;
|
||||
private List<Handler.Factory<? extends Handler>> handlers = new LinkedList<>();
|
||||
private final List<Handler.Factory<? extends Handler>> handlers = new LinkedList<>();
|
||||
|
||||
private static final List<Handler.Factory<? extends Handler>> defaultHandlers = new LinkedList<>();
|
||||
|
||||
@@ -146,13 +141,14 @@ public abstract class AbstractSessionManager implements SessionManager {
|
||||
return BYPASS_PERMISSION_TEST.test(world, player);
|
||||
}
|
||||
|
||||
return bypassCache.getUnchecked(new WorldPlayerTuple(world, player));
|
||||
var bypassCacheKey = new BypassCacheKey(world.getName(), player.getUniqueId());
|
||||
return bypassCache.asMap().computeIfAbsent(bypassCacheKey, (_) -> BYPASS_PERMISSION_TEST.test(world, player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetState(LocalPlayer player) {
|
||||
checkNotNull(player, "player");
|
||||
@Nullable Session session = getIfPresentInternal(new CacheKey(player));
|
||||
@Nullable Session session = getIfPresentInternal(player);
|
||||
if (session != null) {
|
||||
session.resetState(player);
|
||||
}
|
||||
@@ -161,13 +157,13 @@ public abstract class AbstractSessionManager implements SessionManager {
|
||||
@Override
|
||||
@Nullable
|
||||
public Session getIfPresent(LocalPlayer player) {
|
||||
return getIfPresentInternal(new CacheKey(player));
|
||||
return getIfPresentInternal(player);
|
||||
}
|
||||
|
||||
private Session getIfPresentInternal(CacheKey cacheKey) {
|
||||
@Nullable Session session = sessions.getIfPresent(cacheKey);
|
||||
private Session getIfPresentInternal(LocalPlayer player) {
|
||||
@Nullable Session session = sessions.getIfPresent(player.getUniqueId());
|
||||
if (session != null) {
|
||||
session.ensureInitialized(cacheKey.playerRef.get(), this::initializeSession);
|
||||
session.ensureInitialized(player, this::initializeSession);
|
||||
return session;
|
||||
}
|
||||
return null;
|
||||
@@ -175,7 +171,7 @@ public abstract class AbstractSessionManager implements SessionManager {
|
||||
|
||||
@Override
|
||||
public Session get(LocalPlayer player) {
|
||||
Session session = sessions.asMap().computeIfAbsent(new CacheKey(player), (k) -> new Session(this));
|
||||
Session session = sessions.asMap().computeIfAbsent(player.getUniqueId(), (_) -> new Session(this));
|
||||
session.ensureInitialized(player, this::initializeSession);
|
||||
return session;
|
||||
}
|
||||
@@ -192,27 +188,6 @@ public abstract class AbstractSessionManager implements SessionManager {
|
||||
session.initialize(player);
|
||||
}
|
||||
|
||||
protected static final class CacheKey {
|
||||
final WeakReference<LocalPlayer> playerRef;
|
||||
final UUID uuid;
|
||||
|
||||
CacheKey(LocalPlayer player) {
|
||||
playerRef = new WeakReference<>(player);
|
||||
uuid = player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CacheKey cacheKey = (CacheKey) o;
|
||||
return uuid.equals(cacheKey.uuid);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return uuid.hashCode();
|
||||
}
|
||||
record BypassCacheKey(String worldName, UUID playerUUID) {
|
||||
}
|
||||
}
|
||||
@@ -143,6 +143,9 @@ public class Session {
|
||||
for (Handler handler : handlers.values()) {
|
||||
handler.uninitialize(player, location, set);
|
||||
}
|
||||
|
||||
lastValid = null;
|
||||
lastRegionSet = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,11 +164,12 @@ public class Session {
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-initialize the session.
|
||||
* Restore handler-managed state and then re-initialize the session.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
public void resetState(LocalPlayer player) {
|
||||
uninitialize(player);
|
||||
initialize(player);
|
||||
needRefresh.set(true);
|
||||
}
|
||||
@@ -223,6 +227,12 @@ public class Session {
|
||||
*/
|
||||
@Nullable
|
||||
public Location testMoveTo(LocalPlayer player, Location to, MoveType moveType, boolean forced) {
|
||||
if (lastValid == null) {
|
||||
// If lastValid is null, the session has not yet been initialized. This shouldn't happen, but theoretically
|
||||
// can due to Bukkit event orderings.
|
||||
return null;
|
||||
}
|
||||
|
||||
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
|
||||
|
||||
if (!forced && needRefresh.getAndSet(false)) {
|
||||
|
||||
@@ -41,14 +41,14 @@ public interface SessionManager {
|
||||
boolean hasBypass(LocalPlayer player, World world);
|
||||
|
||||
/**
|
||||
* Re-initialize handlers and clear "last position," "last state," etc.
|
||||
* information for all players.
|
||||
* Restore handler-managed state, re-initialize handlers, and clear
|
||||
* "last position," "last state," etc. information for all players.
|
||||
*/
|
||||
void resetAllStates();
|
||||
|
||||
/**
|
||||
* Re-initialize handlers and clear "last position," "last state," etc.
|
||||
* information.
|
||||
* Restore handler-managed state, re-initialize handlers, and clear
|
||||
* "last position," "last state," etc. information.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.sk89q.worldguard.session;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public class WorldPlayerTuple {
|
||||
|
||||
private final World world;
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class ApplicableRegionsReport extends DataReport {
|
||||
|
||||
public ApplicableRegionsReport(LocalPlayer player) {
|
||||
super("Applicable regions");
|
||||
BlockVector3 position = player.getBlockIn().toVector().toBlockPoint();
|
||||
BlockVector3 position = player.getBlockLocation().toVector().toBlockPoint();
|
||||
append("Location", player.getWorld().getName() + " @ " + position);
|
||||
RegionManager mgr = WorldGuard.getInstance().getPlatform().getRegionContainer().get(player.getWorld());
|
||||
if (mgr == null) {
|
||||
|
||||
Reference in new issue
Block a user