1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Finished fix for #2636 and fixed a threading issue with BlockStates

This commit is contained in:
TheBusyBiscuit 2021-01-14 11:58:52 +01:00
parent 42631a1165
commit 7826b2359a
11 changed files with 108 additions and 17 deletions

View File

@ -34,6 +34,8 @@
* Fixed elevator floor order * Fixed elevator floor order
* Fixed #2449 * Fixed #2449
* Fixed #2511 * Fixed #2511
* Fixed #2636
* Fixed a threading issue related to BlockStates and persistent data
## Release Candidate 19 (11 Jan 2021) ## Release Candidate 19 (11 Jan 2021)

View File

@ -10,6 +10,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
@ -50,7 +51,10 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/ */
public class BlockListener implements Listener { public class BlockListener implements Listener {
private final SlimefunPlugin plugin;
public BlockListener(@Nonnull SlimefunPlugin plugin) { public BlockListener(@Nonnull SlimefunPlugin plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }
@ -63,19 +67,26 @@ public class BlockListener implements Listener {
*/ */
Block block = e.getBlock(); Block block = e.getBlock();
// Fixes #2636
if (e.getBlockReplacedState().getType().isAir()) { if (e.getBlockReplacedState().getType().isAir()) {
SlimefunItem sfItem = BlockStorage.check(block); SlimefunItem sfItem = BlockStorage.check(block);
if (sfItem != null) { if (sfItem != null) {
/* /*
* Temp fix for #2636 * We can move the TickerTask synchronization to an async task to
* for (ItemStack item : sfItem.getDrops()) { * avoid blocking the main Thread here.
* if (item != null && !item.getType().isAir()) {
* block.getWorld().dropItemNaturally(block.getLocation(), item);
* }
* }
*/ */
BlockStorage.clearBlockInfo(block); Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
if (!SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) {
for (ItemStack item : sfItem.getDrops()) {
if (item != null && !item.getType().isAir()) {
SlimefunPlugin.runSync(() -> block.getWorld().dropItemNaturally(block.getLocation(), item));
}
}
BlockStorage.clearBlockInfo(block);
}
});
} }
} else if (BlockStorage.hasBlockInfo(e.getBlock())) { } else if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true); e.setCancelled(true);
@ -119,7 +130,7 @@ public class BlockListener implements Listener {
int fortune = getBonusDropsWithFortune(item, e.getBlock()); int fortune = getBonusDropsWithFortune(item, e.getBlock());
List<ItemStack> drops = new ArrayList<>(); List<ItemStack> drops = new ArrayList<>();
if (item.getType() != Material.AIR) { if (!item.getType().isAir()) {
callToolHandler(e, item, fortune, drops); callToolHandler(e, item, fortune, drops);
} }
@ -159,9 +170,13 @@ public class BlockListener implements Listener {
SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getId()); SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getId());
if (blockHandler != null) { if (blockHandler != null) {
if (!blockHandler.onBreak(e.getPlayer(), e.getBlock(), sfItem, UnregisterReason.PLAYER_BREAK)) { try {
e.setCancelled(true); if (!blockHandler.onBreak(e.getPlayer(), e.getBlock(), sfItem, UnregisterReason.PLAYER_BREAK)) {
return; e.setCancelled(true);
return;
}
} catch (Exception | LinkageError x) {
sfItem.error("Something went wrong while triggering a BlockHandler", x);
} }
} else { } else {
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onBlockBreak(e, item, fortune, drops)); sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onBlockBreak(e, item, fortune, drops));

View File

@ -94,7 +94,7 @@ public class BlockPhysicsListener implements Listener {
Location loc = block.getLocation(); Location loc = block.getLocation();
// Fixes #2496 - Make sure it is not a moving block // Fixes #2496 - Make sure it is not a moving block
if (SlimefunPlugin.getTickerTask().isReserved(loc)) { if (SlimefunPlugin.getTickerTask().isOccupiedSoon(loc)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }

View File

@ -3,8 +3,16 @@ package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
/**
* A {@link GEOResource} which consists of nether ice.
* It can only be found in the nether.
*
* @author TheBusyBiscuit
*
*/
class NetherIceResource extends SlimefunResource { class NetherIceResource extends SlimefunResource {
NetherIceResource() { NetherIceResource() {

View File

@ -3,8 +3,21 @@ package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.OilPump;
/**
* A {@link GEOResource} which consists of buckets of Oil.
* It cannot be obtained via a {@link GEOMiner} but instead requires
* and {@link OilPump}.
*
* @author TheBusyBiscuit
*
* @see OilPump
*
*/
class OilResource extends SlimefunResource { class OilResource extends SlimefunResource {
OilResource() { OilResource() {

View File

@ -3,8 +3,15 @@ package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
/**
* A {@link GEOResource} which consists of Salt.
*
* @author TheBusyBiscuit
*
*/
class SaltResource extends SlimefunResource { class SaltResource extends SlimefunResource {
SaltResource() { SaltResource() {

View File

@ -10,6 +10,17 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
/**
* This is an abstract parent class for any {@link GEOResource}
* that is added by Slimefun itself. It is package-private, therefore
* only classes inside this package can access it.
* <p>
* It just provides a bit of a convenience for us to reduce redundancies
* in our {@link GEOResource} implementations.
*
* @author TheBusyBiscuit
*
*/
abstract class SlimefunResource implements GEOResource { abstract class SlimefunResource implements GEOResource {
private final NamespacedKey key; private final NamespacedKey key;

View File

@ -3,8 +3,15 @@ package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
/**
* A {@link GEOResource} which consists of small chunks of Uranium.
*
* @author TheBusyBiscuit
*
*/
class UraniumResource extends SlimefunResource { class UraniumResource extends SlimefunResource {
UraniumResource() { UraniumResource() {

View File

@ -252,10 +252,26 @@ public class TickerTask implements Runnable {
* *
* @return Whether this {@link Location} has been reserved and will be filled upon the next tick * @return Whether this {@link Location} has been reserved and will be filled upon the next tick
*/ */
public boolean isReserved(@Nonnull Location l) { public boolean isOccupiedSoon(@Nonnull Location l) {
Validate.notNull(l, "Null is not a valid Location!");
return movingQueue.containsValue(l); return movingQueue.containsValue(l);
} }
/**
* This method checks if a given {@link Location} will be deleted on the next tick.
*
* @param l
* The {@link Location} to check
*
* @return Whether this {@link Location} will be deleted on the next tick
*/
public boolean isDeletedSoon(@Nonnull Location l) {
Validate.notNull(l, "Null is not a valid Location!");
return deletionQueue.containsKey(l);
}
/** /**
* This returns the delay between ticks * This returns the delay between ticks
* *

View File

@ -151,7 +151,7 @@ public class SlimefunItem implements Placeable {
* The result of crafting this item * The result of crafting this item
*/ */
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public SlimefunItem(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) { public SlimefunItem(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, @Nullable ItemStack recipeOutput) {
Validate.notNull(category, "'category' is not allowed to be null!"); Validate.notNull(category, "'category' is not allowed to be null!");
Validate.notNull(item, "'item' is not allowed to be null!"); Validate.notNull(item, "'item' is not allowed to be null!");
Validate.notNull(recipeType, "'recipeType' is not allowed to be null!"); Validate.notNull(recipeType, "'recipeType' is not allowed to be null!");
@ -263,10 +263,21 @@ public class SlimefunItem implements Placeable {
* @return The linked {@link Research} or null * @return The linked {@link Research} or null
*/ */
@Nullable @Nullable
public Research getResearch() { public final Research getResearch() {
return research; return research;
} }
/**
* This returns whether this {@link SlimefunItem} has a {@link Research}
* assigned to it.
* It is equivalent to a null check performed on {@link #getResearch()}.
*
* @return Whether this {@link SlimefunItem} has a {@link Research}
*/
public final boolean hasResearch() {
return research != null;
}
/** /**
* This returns a {@link Set} containing all instances of {@link ItemSetting} for this {@link SlimefunItem}. * This returns a {@link Set} containing all instances of {@link ItemSetting} for this {@link SlimefunItem}.
* *
@ -490,7 +501,7 @@ public class SlimefunItem implements Placeable {
if (itemStackTemplate.getAmount() != 1) { if (itemStackTemplate.getAmount() != 1) {
// @formatter:off // @formatter:off
warn("This item has an illegal stack size: " + itemStackTemplate.getAmount() warn("This item has an illegal stack size: " + itemStackTemplate.getAmount()
+ "An Item size of 1 is recommended. Please inform the autho of " + addon.getName() + ". An Item size of 1 is recommended. Please inform the author(s) of " + addon.getName()
+ " to fix this. Crafting Results with amounts of higher should be handled" + " to fix this. Crafting Results with amounts of higher should be handled"
+ " via the recipeOutput parameter!"); + " via the recipeOutput parameter!");
// @formatter:on // @formatter:on

View File

@ -673,7 +673,8 @@ public class BlockStorage {
@Nullable @Nullable
public static String checkID(@Nonnull Block b) { public static String checkID(@Nonnull Block b) {
if (SlimefunPlugin.getBlockDataService().isTileEntity(b.getType())) { // Only access the BlockState when on the main thread
if (Bukkit.isPrimaryThread() && SlimefunPlugin.getBlockDataService().isTileEntity(b.getType())) {
Optional<String> blockData = SlimefunPlugin.getBlockDataService().getBlockData(b); Optional<String> blockData = SlimefunPlugin.getBlockDataService().getBlockData(b);
if (blockData.isPresent()) { if (blockData.isPresent()) {