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.core.util; 020 021import com.plotsquared.core.PlotSquared; 022import com.plotsquared.core.configuration.ConfigurationSection; 023import com.plotsquared.core.configuration.caption.TranslatableCaption; 024import com.plotsquared.core.player.ConsolePlayer; 025import com.plotsquared.core.plot.BlockBucket; 026import com.sk89q.worldedit.world.block.BlockState; 027import net.kyori.adventure.text.minimessage.Template; 028import org.apache.logging.log4j.LogManager; 029import org.apache.logging.log4j.Logger; 030import org.checkerframework.checker.nullness.qual.NonNull; 031 032import java.util.Collection; 033import java.util.HashMap; 034import java.util.List; 035import java.util.Map; 036 037/** 038 * Converts legacy configurations into the new (BlockBucket) format 039 */ 040@SuppressWarnings("unused") 041public final class LegacyConverter { 042 043 public static final String CONFIGURATION_VERSION = "post_flattening"; 044 private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + LegacyConverter.class.getSimpleName()); 045 private static final HashMap<String, ConfigurationType> TYPE_MAP = new HashMap<>(); 046 047 static { 048 TYPE_MAP.put("plot.filling", ConfigurationType.BLOCK_LIST); 049 TYPE_MAP.put("plot.floor", ConfigurationType.BLOCK_LIST); 050 TYPE_MAP.put("wall.filling", ConfigurationType.BLOCK); 051 TYPE_MAP.put("wall.block_claimed", ConfigurationType.BLOCK); 052 TYPE_MAP.put("wall.block", ConfigurationType.BLOCK); 053 TYPE_MAP.put("road.block", ConfigurationType.BLOCK); 054 } 055 056 private final ConfigurationSection configuration; 057 058 public LegacyConverter(final @NonNull ConfigurationSection configuration) { 059 this.configuration = configuration; 060 } 061 062 private BlockBucket blockToBucket(final @NonNull String block) { 063 final BlockState plotBlock = PlotSquared.platform().worldUtil().getClosestBlock(block).best; 064 return BlockBucket.withSingle(plotBlock); 065 } 066 067 private void setString( 068 final @NonNull ConfigurationSection section, 069 final @NonNull String string, final @NonNull BlockBucket blocks 070 ) { 071 if (!section.contains(string)) { 072 throw new IllegalArgumentException(String.format("No such key: %s", string)); 073 } 074 section.set(string, blocks.toString()); 075 } 076 077 private BlockBucket blockListToBucket(final @NonNull BlockState[] blocks) { 078 final Map<BlockState, Integer> counts = new HashMap<>(); 079 for (final BlockState block : blocks) { 080 counts.putIfAbsent(block, 0); 081 counts.put(block, counts.get(block) + 1); 082 } 083 boolean includeRatios = false; 084 for (final Integer integer : counts.values()) { 085 if (integer > 1) { 086 includeRatios = true; 087 break; 088 } 089 } 090 final BlockBucket bucket = new BlockBucket(); 091 if (includeRatios) { 092 for (final Map.Entry<BlockState, Integer> count : counts.entrySet()) { 093 bucket.addBlock(count.getKey(), count.getValue()); 094 } 095 } else { 096 counts.keySet().forEach(bucket::addBlock); 097 } 098 return bucket; 099 } 100 101 private BlockState[] splitBlockList(final @NonNull List<String> list) { 102 return list.stream().map(s -> PlotSquared.platform().worldUtil().getClosestBlock(s).best) 103 .toArray(BlockState[]::new); 104 } 105 106 private void convertBlock( 107 final @NonNull ConfigurationSection section, 108 final @NonNull String key, 109 final @NonNull String block 110 ) { 111 final BlockBucket bucket = this.blockToBucket(block); 112 this.setString(section, key, bucket); 113 ConsolePlayer.getConsole().sendMessage( 114 TranslatableCaption.of("legacyconfig.legacy_config_replaced"), 115 Template.of("value1", block), 116 Template.of("value2", bucket.toString()) 117 ); 118 } 119 120 private void convertBlockList( 121 final @NonNull ConfigurationSection section, 122 final @NonNull String key, 123 final @NonNull List<String> blockList 124 ) { 125 final BlockState[] blocks = this.splitBlockList(blockList); 126 final BlockBucket bucket = this.blockListToBucket(blocks); 127 this.setString(section, key, bucket); 128 ConsolePlayer.getConsole() 129 .sendMessage( 130 TranslatableCaption.of("legacyconfig.legacy_config_replaced"), 131 Template.of("value1", plotBlockArrayString(blocks)), 132 Template.of("value2", bucket.toString()) 133 ); 134 } 135 136 private String plotBlockArrayString(final @NonNull BlockState[] blocks) { 137 final StringBuilder builder = new StringBuilder(); 138 for (int i = 0; i < blocks.length; i++) { 139 builder.append(blocks[i].toString()); 140 if ((i + 1) < blocks.length) { 141 builder.append(","); 142 } 143 } 144 return builder.toString(); 145 } 146 147 public void convert() { 148 // Section is the "worlds" section 149 final Collection<String> worlds = this.configuration.getKeys(false); 150 for (final String world : worlds) { 151 final ConfigurationSection worldSection = configuration.getConfigurationSection(world); 152 for (final Map.Entry<String, ConfigurationType> entry : TYPE_MAP.entrySet()) { 153 if (worldSection.contains(entry.getKey())) { 154 if (entry.getValue() == ConfigurationType.BLOCK) { 155 this.convertBlock(worldSection, entry.getKey(), 156 worldSection.getString(entry.getKey()) 157 ); 158 } else { 159 this.convertBlockList(worldSection, entry.getKey(), 160 worldSection.getStringList(entry.getKey()) 161 ); 162 } 163 } 164 } 165 } 166 } 167 168 private enum ConfigurationType { 169 BLOCK, 170 BLOCK_LIST 171 } 172 173}