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.util;
020
021import com.plotsquared.bukkit.entity.EntityWrapper;
022import com.plotsquared.bukkit.entity.ReplicatingEntityWrapper;
023import com.plotsquared.core.location.Location;
024import com.plotsquared.core.location.PlotLoc;
025import com.sk89q.worldedit.bukkit.BukkitWorld;
026import com.sk89q.worldedit.math.BlockVector3;
027import com.sk89q.worldedit.regions.CuboidRegion;
028import com.sk89q.worldedit.world.block.BaseBlock;
029import org.apache.logging.log4j.LogManager;
030import org.apache.logging.log4j.Logger;
031import org.bukkit.Chunk;
032import org.bukkit.World;
033import org.bukkit.entity.Entity;
034import org.bukkit.entity.Player;
035
036import java.util.HashMap;
037import java.util.HashSet;
038import java.util.Map;
039import java.util.Set;
040
041public class ContentMap {
042
043    private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + ContentMap.class.getSimpleName());
044
045    final Set<EntityWrapper> entities;
046    final Map<PlotLoc, BaseBlock[]> allBlocks;
047
048    ContentMap() {
049        this.entities = new HashSet<>();
050        this.allBlocks = new HashMap<>();
051    }
052
053    public void saveRegion(BukkitWorld world, int x1, int x2, int z1, int z2) {
054        if (z1 > z2) {
055            int tmp = z1;
056            z1 = z2;
057            z2 = tmp;
058        }
059        if (x1 > x2) {
060            int tmp = x1;
061            x1 = x2;
062            x2 = tmp;
063        }
064        for (int x = x1; x <= x2; x++) {
065            for (int z = z1; z <= z2; z++) {
066                saveBlocks(world, x, z);
067            }
068        }
069    }
070
071    void saveEntitiesOut(Chunk chunk, CuboidRegion region) {
072        for (Entity entity : chunk.getEntities()) {
073            Location location = BukkitUtil.adapt(entity.getLocation());
074            int x = location.getX();
075            int z = location.getZ();
076            if (BukkitChunkManager.isIn(region, x, z)) {
077                continue;
078            }
079            if (entity.getVehicle() != null) {
080                continue;
081            }
082            EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2);
083            wrap.saveEntity();
084            this.entities.add(wrap);
085        }
086    }
087
088    void saveEntitiesIn(Chunk chunk, CuboidRegion region, boolean delete) {
089        for (Entity entity : chunk.getEntities()) {
090            Location location = BukkitUtil.adapt(entity.getLocation());
091            int x = location.getX();
092            int z = location.getZ();
093            if (!BukkitChunkManager.isIn(region, x, z)) {
094                continue;
095            }
096            if (entity.getVehicle() != null) {
097                continue;
098            }
099            EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2);
100            wrap.saveEntity();
101            this.entities.add(wrap);
102            if (delete) {
103                if (!(entity instanceof Player)) {
104                    entity.remove();
105                }
106            }
107        }
108    }
109
110    void restoreEntities(World world) {
111        for (EntityWrapper entity : this.entities) {
112            try {
113                entity.spawn(world, 0, 0);
114            } catch (Exception e) {
115                LOGGER.error("Failed to restore entity", e);
116            }
117        }
118        this.entities.clear();
119    }
120
121    private void saveBlocks(BukkitWorld world, int x, int z) {
122        BaseBlock[] ids = new BaseBlock[world.getMaxY() - world.getMinY() + 1];
123        for (short yIndex = 0; yIndex <= world.getMaxY() - world.getMinY(); yIndex++) {
124            BaseBlock block = world.getFullBlock(BlockVector3.at(x, yIndex + world.getMinY(), z));
125            ids[yIndex] = block;
126        }
127        PlotLoc loc = new PlotLoc(x, z);
128        this.allBlocks.put(loc, ids);
129    }
130
131}