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.Field; 035import java.lang.reflect.Method; 036 037import static com.plotsquared.core.util.ReflectionUtils.getRefClass; 038 039public class SingleWorldListener implements Listener { 040 041 private final Method methodGetHandleChunk; 042 private Field shouldSave = null; 043 044 public SingleWorldListener() throws Exception { 045 ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); 046 this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod(); 047 try { 048 if (PlotSquared.platform().serverVersion()[1] < 17) { 049 ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk"); 050 if (PlotSquared.platform().serverVersion()[1] == 13) { 051 this.shouldSave = classChunk.getField("mustSave").getRealField(); 052 } else { 053 this.shouldSave = classChunk.getField("s").getRealField(); 054 } 055 } else if (PlotSquared.platform().serverVersion()[1] == 17) { 056 ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk"); 057 this.shouldSave = classChunk.getField("r").getRealField(); 058 } else if (PlotSquared.platform().serverVersion()[1] == 18) { 059 ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.IChunkAccess"); 060 this.shouldSave = classChunk.getField("b").getRealField(); 061 } 062 } catch (NoSuchFieldException e) { 063 e.printStackTrace(); 064 } 065 } 066 067 public void markChunkAsClean(Chunk chunk) { 068 try { 069 Object nmsChunk = methodGetHandleChunk.invoke(chunk); 070 if (shouldSave != null) { 071 this.shouldSave.set(nmsChunk, false); 072 } 073 } catch (Throwable e) { 074 e.printStackTrace(); 075 } 076 } 077 078 private void handle(ChunkEvent event) { 079 World world = event.getWorld(); 080 String name = world.getName(); 081 PlotAreaManager man = PlotSquared.get().getPlotAreaManager(); 082 if (!(man instanceof SinglePlotAreaManager)) { 083 return; 084 } 085 if (!SinglePlotArea.isSinglePlotWorld(name)) { 086 return; 087 } 088 089 markChunkAsClean(event.getChunk()); 090 } 091 092 // @EventHandler 093 // public void onPopulate(ChunkPopulateEvent event) { 094 // handle(event); 095 // } 096 097 @EventHandler(priority = EventPriority.LOWEST) 098 public void onChunkLoad(ChunkLoadEvent event) { 099 handle(event); 100 } 101 102}