001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.bukkit.queue; 020 021import com.plotsquared.bukkit.schematic.StateWrapper; 022import com.plotsquared.core.queue.DelegateQueueCoordinator; 023import com.sk89q.jnbt.CompoundTag; 024import com.sk89q.worldedit.bukkit.BukkitAdapter; 025import com.sk89q.worldedit.entity.Entity; 026import com.sk89q.worldedit.function.pattern.Pattern; 027import com.sk89q.worldedit.math.BlockVector3; 028import com.sk89q.worldedit.world.block.BaseBlock; 029import com.sk89q.worldedit.world.block.BlockState; 030import org.apache.logging.log4j.LogManager; 031import org.apache.logging.log4j.Logger; 032import org.bukkit.Location; 033import org.bukkit.entity.EntityType; 034import org.bukkit.generator.LimitedRegion; 035import org.checkerframework.checker.nullness.qual.NonNull; 036 037/** 038 * Wraps a {@link LimitedRegion} inside a {@link com.plotsquared.core.queue.QueueCoordinator} so it can be written to. 039 * 040 * @since 6.9.0 041 */ 042public class LimitedRegionWrapperQueue extends DelegateQueueCoordinator { 043 044 private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + LimitedRegionWrapperQueue.class.getSimpleName()); 045 046 private final LimitedRegion limitedRegion; 047 private boolean useOtherRestoreTagMethod = false; 048 049 /** 050 * @since 6.9.0 051 */ 052 public LimitedRegionWrapperQueue(LimitedRegion limitedRegion) { 053 super(null); 054 this.limitedRegion = limitedRegion; 055 } 056 057 @Override 058 public boolean setBlock(final int x, final int y, final int z, @NonNull final Pattern pattern) { 059 return setBlock(x, y, z, pattern.applyBlock(BlockVector3.at(x, y, z))); 060 } 061 062 @Override 063 public boolean setBlock(final int x, final int y, final int z, @NonNull final BaseBlock id) { 064 boolean result = setBlock(x, y, z, id.toImmutableState()); 065 if (result && id.hasNbtData()) { 066 CompoundTag tag = id.getNbtData(); 067 StateWrapper sw = new StateWrapper(tag); 068 try { 069 if (useOtherRestoreTagMethod && getWorld() != null) { 070 sw.restoreTag(getWorld().getName(), x, y, z); 071 } else { 072 sw.restoreTag(limitedRegion.getBlockState(x, y, z).getBlock()); 073 } 074 } catch (IllegalArgumentException e) { 075 LOGGER.error("Error attempting to populate tile entity into the world at location {},{},{}", x, y, z, e); 076 return false; 077 } catch (IllegalStateException e) { 078 useOtherRestoreTagMethod = true; 079 LOGGER.warn("IllegalStateException attempting to populate tile entity into the world at location {},{},{}. " + 080 "Possibly on <=1.17.1, switching to secondary method.", x, y, z, e); 081 } 082 } 083 return result; 084 } 085 086 @Override 087 public boolean setBlock(final int x, final int y, final int z, @NonNull final BlockState id) { 088 try { 089 limitedRegion.setType(x, y, z, BukkitAdapter.adapt(id.getBlockType())); 090 limitedRegion.setBlockData(x, y, z, BukkitAdapter.adapt(id)); 091 } catch (IllegalArgumentException e) { 092 LOGGER.error("Error attempting to populate block into the world at location {},{},{}", x, y, z, e); 093 return false; 094 } 095 return true; 096 } 097 098 @Override 099 public boolean setEntity(@NonNull final Entity entity) { 100 EntityType type = BukkitAdapter.adapt(entity.getState().getType()); 101 double x = entity.getLocation().getX(); 102 double y = entity.getLocation().getY(); 103 double z = entity.getLocation().getZ(); 104 Location location = new Location(limitedRegion.getWorld(), x, y, z); 105 try { 106 limitedRegion.spawnEntity(location, type); 107 } catch (IllegalArgumentException e) { 108 LOGGER.error("Error attempting to populate entity into the world at location {},{},{}", (int) x, (int) y, (int) z, e); 109 return false; 110 } 111 return true; 112 } 113 114 @Override 115 public boolean setTile(final int x, final int y, final int z, @NonNull final CompoundTag tag) { 116 StateWrapper sw = new StateWrapper(tag); 117 try { 118 return sw.restoreTag(limitedRegion.getBlockState(x, y, z).getBlock()); 119 } catch (IllegalArgumentException e) { 120 LOGGER.error("Error attempting to populate tile entity into the world at location {},{},{}", x, y, z, e); 121 return false; 122 } 123 } 124 125 @Override 126 public boolean isSettingTiles() { 127 return true; 128 } 129 130}