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.listener; 020 021import com.plotsquared.core.PlotSquared; 022import com.plotsquared.core.plot.world.PlotAreaManager; 023import com.plotsquared.core.plot.world.SinglePlotArea; 024import com.plotsquared.core.plot.world.SinglePlotAreaManager; 025import com.plotsquared.core.util.ReflectionUtils; 026import org.bukkit.Chunk; 027import org.bukkit.World; 028import org.bukkit.event.EventHandler; 029import org.bukkit.event.EventPriority; 030import org.bukkit.event.Listener; 031import org.bukkit.event.world.ChunkEvent; 032import org.bukkit.event.world.ChunkLoadEvent; 033 034import java.lang.reflect.Method; 035 036import static com.plotsquared.core.util.ReflectionUtils.getRefClass; 037 038public class SingleWorldListener implements Listener { 039 040 private final Method methodSetUnsaved; 041 private Method methodGetHandleChunk; 042 private Object objChunkStatusFull = null; 043 044 public SingleWorldListener() throws Exception { 045 ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); 046 ReflectionUtils.RefClass classChunkAccess = getRefClass("net.minecraft.world.level.chunk.IChunkAccess"); 047 this.methodSetUnsaved = classChunkAccess.getMethod("a", boolean.class).getRealMethod(); 048 try { 049 this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod(); 050 } catch (NoSuchMethodException ignored) { 051 try { 052 ReflectionUtils.RefClass classChunkStatus = getRefClass("net.minecraft.world.level.chunk.ChunkStatus"); 053 this.objChunkStatusFull = classChunkStatus.getRealClass().getField("n").get(null); 054 this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle", classChunkStatus.getRealClass()).getRealMethod(); 055 } catch (NoSuchMethodException ex) { 056 throw new RuntimeException(ex); 057 } 058 } 059 } 060 061 public void markChunkAsClean(Chunk chunk) { 062 try { 063 Object nmsChunk = objChunkStatusFull != null 064 ? this.methodGetHandleChunk.invoke(chunk, objChunkStatusFull) 065 : this.methodGetHandleChunk.invoke(chunk); 066 methodSetUnsaved.invoke(nmsChunk, false); 067 } catch (Throwable e) { 068 e.printStackTrace(); 069 } 070 } 071 072 private void handle(ChunkEvent event) { 073 World world = event.getWorld(); 074 String name = world.getName(); 075 PlotAreaManager man = PlotSquared.get().getPlotAreaManager(); 076 if (!(man instanceof SinglePlotAreaManager)) { 077 return; 078 } 079 if (!SinglePlotArea.isSinglePlotWorld(name)) { 080 return; 081 } 082 int x = event.getChunk().getX(); 083 int z = event.getChunk().getZ(); 084 if (x < 16 && x > -16 && z < 16 && z > -16) { 085 // Allow spawn to generate 086 return; 087 } 088 markChunkAsClean(event.getChunk()); 089 } 090 091 // @EventHandler 092 // public void onPopulate(ChunkPopulateEvent event) { 093 // handle(event); 094 // } 095 096 @EventHandler(priority = EventPriority.LOWEST) 097 public void onChunkLoad(ChunkLoadEvent event) { 098 handle(event); 099 } 100 101}