1075 lines
54 KiB
Java
1075 lines
54 KiB
Java
package com.boydti.fawe.util;
|
|
|
|
import com.boydti.fawe.Fawe;
|
|
import com.boydti.fawe.beta.implementation.filter.block.SingleFilterBlock;
|
|
import com.boydti.fawe.config.Settings;
|
|
import com.boydti.fawe.util.image.ImageUtil;
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.reflect.TypeToken;
|
|
import com.google.gson.stream.JsonReader;
|
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
|
import com.sk89q.worldedit.function.mask.Mask;
|
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|
import com.sk89q.worldedit.math.BlockVector3;
|
|
import com.sk89q.worldedit.util.PropertiesConfiguration;
|
|
import com.sk89q.worldedit.util.report.Unreported;
|
|
import com.sk89q.worldedit.world.block.BlockType;
|
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
|
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
import it.unimi.dsi.fastutil.ints.IntArraySet;
|
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.BufferedInputStream;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.lang.reflect.Type;
|
|
import java.net.URL;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.security.AccessControlException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.regex.Pattern;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipFile;
|
|
import javax.imageio.ImageIO;
|
|
|
|
import static org.apache.logging.log4j.LogManager.getLogger;
|
|
|
|
// TODO FIXME
|
|
public class TextureUtil implements TextureHolder {
|
|
|
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
|
|
|
private static final int[] FACTORS = new int[766];
|
|
|
|
static {
|
|
for (int i = 1; i < FACTORS.length; i++) {
|
|
FACTORS[i] = 65535 / i;
|
|
}
|
|
}
|
|
|
|
private final File folder;
|
|
protected int[] blockColors = new int[BlockTypes.size()];
|
|
protected long[] blockDistance = new long[BlockTypes.size()];
|
|
protected long[] distances;
|
|
protected int[] validColors;
|
|
protected int[] validBlockIds;
|
|
protected int[] validLayerColors;
|
|
protected int[][] validLayerBlocks;
|
|
protected int[] validMixBiomeColors;
|
|
protected long[] validMixBiomeIds;
|
|
/**
|
|
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
|
|
*/
|
|
protected BiomeColor[] validBiomes;
|
|
private BiomeColor[] biomes = new BiomeColor[]{
|
|
// ID Name Temperature, rainfall, grass, foliage colors
|
|
// - note: the colors here are just placeholders, they are computed in the program
|
|
new BiomeColor(0, "ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
// default values of temp and rain
|
|
new BiomeColor(1, "plains", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(2, "desert", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(3, "mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(4, "forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(5, "taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(6, "swamp", 0.8f, 0.9f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(7, "river", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
// default values of temp and rain
|
|
new BiomeColor(8, "nether", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(9, "the_end", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
// default values of temp and rain
|
|
new BiomeColor(10, "frozen_ocean", 0.0f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(11, "frozen_river", 0.0f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(12, "snowy_tundra", 0.0f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(13, "snowy_mountains", 0.0f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(14, "mushroom_fields", 0.9f, 1.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(15, "mushroom_field_shore", 0.9f, 1.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(16, "beach", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(17, "desert_hills", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(18, "wooded_hills", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(19, "taiga_hills", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(20, "mountain_edge", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(21, "jungle", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(22, "jungle_hills", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(23, "jungle_edge", 0.95f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(24, "deep_ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(25, "stone_shore", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(26, "snowy_beach", 0.05f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(27, "birch_forest", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(28, "birch_forest_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(29, "dark_forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(30, "snowy_taiga", -0.5f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(31, "snowy_taiga_hills", -0.5f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(32, "giant_tree_taiga", 0.3f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(33, "giant_tree_taiga_hills", 0.3f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(34, "wooded_mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(35, "savanna", 1.2f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(36, "savanna_plateau", 1.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(37, "badlands", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(38, "wooded_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(39, "badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(40, "small_end_islands", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(41, "end_midlands", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(42, "end_highlands", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(43, "end_barrens", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(44, "warm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(45, "lukewarm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(46, "cold_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(47, "deep_warm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(48, "deep_lukewarm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(49, "deep_cold_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(50, "deep_frozen_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(51, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(52, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(53, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(54, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(55, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(56, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(57, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(58, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(59, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(60, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(61, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(62, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(63, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(64, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(65, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(66, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(67, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(68, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(69, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(70, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(71, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(72, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(73, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(74, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(75, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(76, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(77, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(78, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(79, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(80, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(81, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(82, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(83, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(84, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(85, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(86, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(87, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(88, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(89, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(90, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(91, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(92, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(93, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(94, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(95, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(96, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(97, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(98, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(99, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(100, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(101, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(102, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(103, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(104, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(105, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(106, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(107, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(108, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(109, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(110, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(111, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(112, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(113, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(114, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(115, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(116, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(117, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(118, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(119, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(120, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(121, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(122, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(123, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(124, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(125, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(126, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(127, "the_void", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
// default values of temp and rain; also, no height differences
|
|
new BiomeColor(128, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(129, "sunflower_plains", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(130, "desert_lakes", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(131, "gravelly_mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(132, "flower_forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(133, "taiga_mountains", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(134, "swamp_hills", 0.8f, 0.9f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(135, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(136, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(137, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(138, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(139, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(140, "ice_spikes", 0.0f, 0.5f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(141, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(142, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(143, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(144, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(145, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(146, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(147, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(148, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(149, "modified_jungle", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(150, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(151, "modified_jungle_edge", 0.95f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(152, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(153, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(154, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(155, "tall_birch_forest", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(156, "tall_birch_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(157, "dark_forest_hills", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(158, "snowy_taiga_mountains", -0.5f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(159, "Unknown", -0.5f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(160, "giant_spruce_taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
// special exception, temperature not 0.3
|
|
new BiomeColor(161, "giant_spruce_taiga_hills", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(162, "modified_gravelly_mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(163, "shattered_savanna", 1.1f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(164, "shattered_savanna_plateau", 1.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(165, "eroded_badlands", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(166, "modified_wooded_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(167, "modified_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(168, "bamboo_jungle", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(169, "bamboo_jungle_hills", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(170, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(171, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(172, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(173, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(174, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(175, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(176, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(177, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(178, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(179, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(180, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(181, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(182, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(183, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(184, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(185, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(186, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(187, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(188, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(189, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(190, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(191, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(192, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(193, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(194, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(195, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(196, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(197, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(198, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(199, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(200, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(201, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(202, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(203, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(204, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(205, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(206, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(207, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(208, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(209, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(210, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(211, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(212, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(213, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(214, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(215, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(216, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(217, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(218, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(219, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(220, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(221, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(222, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(223, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(224, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(225, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(226, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(227, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(228, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(229, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(230, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(231, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(232, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(233, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(234, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(235, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(236, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(237, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(238, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(239, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(240, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(241, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(242, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(243, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(244, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(245, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(246, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(247, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(248, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(249, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(250, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(251, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(252, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(253, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(254, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
|
new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F)
|
|
};
|
|
private BlockType[] layerBuffer = new BlockType[2];
|
|
|
|
public TextureUtil() throws FileNotFoundException {
|
|
this(MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TEXTURES));
|
|
}
|
|
|
|
public TextureUtil(File folder) throws FileNotFoundException {
|
|
this.folder = folder;
|
|
if (!folder.exists()) {
|
|
try {
|
|
LOGGER.info("Downloading asset jar from Mojang, please wait...");
|
|
new File(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" + "/.minecraft/versions/").mkdirs();
|
|
try (BufferedInputStream in = new BufferedInputStream(new URL("https://launcher.mojang.com/v1/objects/37fd3c903861eeff3bc24b71eed48f828b5269c8/client.jar").openStream());
|
|
FileOutputStream fileOutputStream = new FileOutputStream(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" + "/.minecraft/versions/1.16.5.jar")) {
|
|
byte[] dataBuffer = new byte[1024];
|
|
int bytesRead;
|
|
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
|
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
|
}
|
|
LOGGER.info("Asset jar down has been downloaded successfully.");
|
|
} catch (IOException e) {
|
|
LOGGER.error("Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar in it.");
|
|
LOGGER.error("If the file exists, please make sure the server has read access to the directory.");
|
|
}
|
|
} catch (AccessControlException e) {
|
|
LOGGER.error("Could not download asset jar. It's likely your file permission are setup improperly and do not allow fetching data from the Mojang servers.");
|
|
LOGGER.error("Please create the following folder manually: `FastAsyncWorldEdit/textures` with `.minecraft/versions` jar in it.");
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public static TextureUtil fromClipboard(Clipboard clipboard) throws FileNotFoundException {
|
|
boolean[] ids = new boolean[BlockTypes.size()];
|
|
for (BlockVector3 pt : clipboard.getRegion()) {
|
|
ids[clipboard.getBlock(pt).getInternalBlockTypeId()] = true;
|
|
}
|
|
HashSet<BlockType> blocks = new HashSet<>();
|
|
for (int typeId = 0; typeId < ids.length; typeId++) {
|
|
if (ids[typeId]) {
|
|
blocks.add(BlockTypes.get(typeId));
|
|
}
|
|
}
|
|
return fromBlocks(blocks);
|
|
}
|
|
|
|
public static TextureUtil fromBlocks(Set<BlockType> blocks) throws FileNotFoundException {
|
|
return new FilteredTextureUtil(Fawe.get().getTextureUtil(), blocks);
|
|
}
|
|
|
|
public static TextureUtil fromMask(Mask mask) throws FileNotFoundException {
|
|
HashSet<BlockType> blocks = new HashSet<>();
|
|
|
|
SingleFilterBlock extent = new SingleFilterBlock();
|
|
new MaskTraverser(mask).reset(extent);
|
|
|
|
TextureUtil tu = Fawe.get().getTextureUtil();
|
|
for (int typeId : tu.getValidBlockIds()) {
|
|
BlockType block = BlockTypes.get(typeId);
|
|
extent.init(0, 0, 0, block.getDefaultState().toBaseBlock());
|
|
if (mask.test(extent)) {
|
|
blocks.add(block);
|
|
}
|
|
}
|
|
return fromBlocks(blocks);
|
|
}
|
|
|
|
protected static int hueDistance(int red1, int green1, int blue1, int red2, int green2,
|
|
int blue2) {
|
|
int total1 = (red1 + green1 + blue1);
|
|
int total2 = (red2 + green2 + blue2);
|
|
if (total1 == 0 || total2 == 0) {
|
|
return 0;
|
|
}
|
|
int factor1 = FACTORS[total1];
|
|
int factor2 = FACTORS[total2];
|
|
long r = (512 * (red1 * factor1 - red2 * factor2)) >> 10;
|
|
long g = (green1 * factor1 - green2 * factor2);
|
|
long b = (767 * (blue1 * factor1 - blue2 * factor2)) >> 10;
|
|
return (int) ((r * r + g * g + b * b) >> 25);
|
|
}
|
|
|
|
@Override
|
|
public TextureUtil getTextureUtil() {
|
|
return this;
|
|
}
|
|
|
|
public BlockType getNearestBlock(int color) {
|
|
long min = Long.MAX_VALUE;
|
|
int closest = 0;
|
|
int red1 = (color >> 16) & 0xFF;
|
|
int green1 = (color >> 8) & 0xFF;
|
|
int blue1 = (color >> 0) & 0xFF;
|
|
int alpha = (color >> 24) & 0xFF;
|
|
for (int i = 0; i < validColors.length; i++) {
|
|
int other = validColors[i];
|
|
if (((other >> 24) & 0xFF) == alpha) {
|
|
long distance = colorDistance(red1, green1, blue1, other);
|
|
if (distance < min) {
|
|
min = distance;
|
|
closest = validBlockIds[i];
|
|
}
|
|
}
|
|
}
|
|
if (min == Long.MAX_VALUE) {
|
|
return null;
|
|
}
|
|
return BlockTypes.get(closest);
|
|
}
|
|
|
|
public BlockType getNearestBlock(BlockType block) {
|
|
int color = getColor(block);
|
|
if (color == 0) {
|
|
return null;
|
|
}
|
|
return getNextNearestBlock(color);
|
|
}
|
|
|
|
public BlockType getNextNearestBlock(int color) {
|
|
long min = Long.MAX_VALUE;
|
|
int closest = 0;
|
|
int red1 = (color >> 16) & 0xFF;
|
|
int green1 = (color >> 8) & 0xFF;
|
|
int blue1 = (color >> 0) & 0xFF;
|
|
int alpha = (color >> 24) & 0xFF;
|
|
for (int i = 0; i < validColors.length; i++) {
|
|
int other = validColors[i];
|
|
if (other != color && ((other >> 24) & 0xFF) == alpha) {
|
|
long distance = colorDistance(red1, green1, blue1, other);
|
|
if (distance < min) {
|
|
min = distance;
|
|
closest = validBlockIds[i];
|
|
}
|
|
}
|
|
}
|
|
if (min == Long.MAX_VALUE) {
|
|
return null;
|
|
}
|
|
return BlockTypes.get(closest);
|
|
}
|
|
|
|
/**
|
|
* Returns the block combined ids as an array.
|
|
*/
|
|
public BlockType[] getNearestLayer(int color) {
|
|
int[] closest = null;
|
|
long min = Long.MAX_VALUE;
|
|
int red1 = (color >> 16) & 0xFF;
|
|
int green1 = (color >> 8) & 0xFF;
|
|
int blue1 = (color >> 0) & 0xFF;
|
|
int alpha = (color >> 24) & 0xFF;
|
|
for (int i = 0; i < validLayerColors.length; i++) {
|
|
int other = validLayerColors[i];
|
|
if (((other >> 24) & 0xFF) == alpha) {
|
|
long distance = colorDistance(red1, green1, blue1, other);
|
|
if (distance < min) {
|
|
min = distance;
|
|
closest = validLayerBlocks[i];
|
|
}
|
|
}
|
|
}
|
|
layerBuffer[0] = BlockTypes.get(closest[0]);
|
|
layerBuffer[1] = BlockTypes.get(closest[1]);
|
|
return layerBuffer;
|
|
}
|
|
|
|
public BlockType getLighterBlock(BlockType block) {
|
|
return getNearestBlock(block, false);
|
|
}
|
|
|
|
public BlockType getDarkerBlock(BlockType block) {
|
|
return getNearestBlock(block, true);
|
|
}
|
|
|
|
public int getColor(BlockType block) {
|
|
return blockColors[block.getInternalId()];
|
|
}
|
|
|
|
public BiomeColor getBiome(int biome) {
|
|
return biomes[biome];
|
|
}
|
|
|
|
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color,
|
|
int biomePriority) {
|
|
BlockType block = getNearestBlock(color);
|
|
TextureUtil.BiomeColor biome = getNearestBiome(color);
|
|
int blockColor = getColor(block);
|
|
blockAndBiomeIdOutput[0] = block.getDefaultState().getOrdinalChar();
|
|
blockAndBiomeIdOutput[1] = (char) biome.id;
|
|
if (colorDistance(biome.grassCombined, color) - biomePriority > colorDistance(blockColor,
|
|
color)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public int getBiomeMix(int[] biomeIdsOutput, int color) {
|
|
long closest = Long.MAX_VALUE;
|
|
int closestAverage = Integer.MAX_VALUE;
|
|
long min = Long.MAX_VALUE;
|
|
int red1 = (color >> 16) & 0xFF;
|
|
int green1 = (color >> 8) & 0xFF;
|
|
int blue1 = (color >> 0) & 0xFF;
|
|
int alpha = (color >> 24) & 0xFF;
|
|
for (int i = 0; i < validMixBiomeColors.length; i++) {
|
|
int other = validMixBiomeColors[i];
|
|
if (((other >> 24) & 0xFF) == alpha) {
|
|
long distance = colorDistance(red1, green1, blue1, other);
|
|
if (distance < min) {
|
|
min = distance;
|
|
closest = validMixBiomeIds[i];
|
|
closestAverage = other;
|
|
}
|
|
}
|
|
}
|
|
biomeIdsOutput[0] = (int) ((closest >> 0) & 0xFF);
|
|
biomeIdsOutput[1] = (int) ((closest >> 8) & 0xFF);
|
|
biomeIdsOutput[2] = (int) ((closest >> 16) & 0xFF);
|
|
return closestAverage;
|
|
}
|
|
|
|
public BiomeColor getNearestBiome(int color) {
|
|
int grass = blockColors[BlockTypes.GRASS_BLOCK.getInternalId()];
|
|
if (grass == 0) {
|
|
return null;
|
|
}
|
|
BiomeColor closest = null;
|
|
long min = Long.MAX_VALUE;
|
|
int red = (color >> 16) & 0xFF;
|
|
int green = (color >> 8) & 0xFF;
|
|
int blue = (color >> 0) & 0xFF;
|
|
for (BiomeColor biome : validBiomes) {
|
|
long distance = colorDistance(red, green, blue, biome.grassCombined);
|
|
if (distance < min) {
|
|
min = distance;
|
|
closest = biome;
|
|
}
|
|
}
|
|
return closest;
|
|
}
|
|
|
|
public File getFolder() {
|
|
return folder;
|
|
}
|
|
|
|
public long colorDistance(int c1, int c2) {
|
|
int red1 = (c1 >> 16) & 0xFF;
|
|
int green1 = (c1 >> 8) & 0xFF;
|
|
int blue1 = (c1 >> 0) & 0xFF;
|
|
return colorDistance(red1, green1, blue1, c2);
|
|
}
|
|
|
|
private BufferedImage readImage(ZipFile zipFile, String name) throws IOException {
|
|
ZipEntry entry = getEntry(zipFile, name);
|
|
if (entry != null) {
|
|
try (InputStream is = zipFile.getInputStream(entry)) {
|
|
return ImageIO.read(is);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private ZipEntry getEntry(ZipFile file, String path) {
|
|
ZipEntry entry = file.getEntry(path);
|
|
if (entry == null) {
|
|
path = path.replace("/", File.separator);
|
|
entry = file.getEntry(path);
|
|
}
|
|
return entry;
|
|
}
|
|
|
|
public void loadModTextures() throws IOException {
|
|
Int2ObjectOpenHashMap<Integer> colorMap = new Int2ObjectOpenHashMap<>();
|
|
Int2ObjectOpenHashMap<Long> distanceMap = new Int2ObjectOpenHashMap<>();
|
|
Gson gson = new Gson();
|
|
if (folder.exists()) {
|
|
// Get all the jar files
|
|
File[] files = folder.listFiles((dir, name) -> name.endsWith(".jar"));
|
|
for (BlockType blockType : BlockTypesCache.values) {
|
|
BlockMaterial material = blockType.getMaterial();
|
|
if (!material.isSolid() || !material.isFullCube()) {
|
|
continue;
|
|
}
|
|
int color = material.getMapColor();
|
|
if (color != 0) {
|
|
colorMap.put(blockType.getInternalId(), (Integer) color);
|
|
}
|
|
}
|
|
if (files.length == 0) {
|
|
new File(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" + "/.minecraft/versions/").mkdirs();
|
|
try (BufferedInputStream in = new BufferedInputStream(new URL("https://launcher.mojang.com/v1/objects/37fd3c903861eeff3bc24b71eed48f828b5269c8/client.jar").openStream());
|
|
FileOutputStream fileOutputStream = new FileOutputStream(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" + "/.minecraft/versions/1.16.5.jar")) {
|
|
byte[] dataBuffer = new byte[1024];
|
|
int bytesRead;
|
|
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
|
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
|
}
|
|
} catch (IOException e) {
|
|
LOGGER.error("Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar or mods in it.");
|
|
LOGGER.error("If the file exists, please make sure the server has read access to the directory.");
|
|
}
|
|
} else {
|
|
for (File file : files) {
|
|
ZipFile zipFile = new ZipFile(file);
|
|
|
|
// Get all the groups in the current jar
|
|
// The vanilla textures are in `assets/minecraft`
|
|
// A jar may contain textures for multiple mods
|
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
|
Set<String> mods = new HashSet<>();
|
|
while (entries.hasMoreElements()) {
|
|
ZipEntry entry = entries.nextElement();
|
|
String name = entry.getName();
|
|
Path path = Paths.get(name);
|
|
if (path.startsWith("assets" + File.separator)) {
|
|
String[] split =
|
|
path.toString().split(Pattern.quote(File.separator));
|
|
if (split.length > 1) {
|
|
String modId = split[1];
|
|
mods.add(modId);
|
|
}
|
|
}
|
|
}
|
|
String modelsDir = "assets/%1$s/models/block/%2$s.json";
|
|
String texturesDir = "assets/%1$s/textures/%2$s.png";
|
|
|
|
Type typeToken = new TypeToken<Map<String, Object>>() {
|
|
}.getType();
|
|
|
|
for (BlockType blockType : BlockTypesCache.values) {
|
|
if (!blockType.getMaterial().isFullCube() || blockType.getId().toLowerCase().contains("shulker")) {
|
|
continue;
|
|
}
|
|
int combined = blockType.getInternalId();
|
|
String id = blockType.getId();
|
|
String[] split = id.split(":", 2);
|
|
String name = split.length == 1 ? id : split[1];
|
|
String nameSpace = split.length == 1 ? "" : split[0];
|
|
|
|
Map<String, String> texturesMap = new ConcurrentHashMap<>();
|
|
// Read models
|
|
String modelFileName = String.format(modelsDir, nameSpace, name);
|
|
ZipEntry entry = getEntry(zipFile, modelFileName);
|
|
if (entry == null) {
|
|
getLogger(TextureUtil.class).error("Cannot find {} in {}", modelFileName, file);
|
|
continue;
|
|
}
|
|
|
|
String textureFileName;
|
|
try (InputStream is = zipFile.getInputStream(entry)) {
|
|
JsonReader reader = new JsonReader(
|
|
new InputStreamReader(is, StandardCharsets.UTF_8));
|
|
Map<String, Object> root = gson.fromJson(reader, typeToken);
|
|
Map<String, Object> textures = (Map) root.get("textures");
|
|
|
|
if (textures == null) {
|
|
continue;
|
|
}
|
|
Set<String> models = new HashSet<>();
|
|
// Get models
|
|
for (Map.Entry<String, Object> stringObjectEntry : textures
|
|
.entrySet()) {
|
|
Object value = stringObjectEntry.getValue();
|
|
if (value instanceof String) {
|
|
models.add((String) value);
|
|
} else if (value instanceof Map) {
|
|
value = ((Map) value).get("model");
|
|
if (value != null) {
|
|
models.add((String) value);
|
|
}
|
|
}
|
|
}
|
|
if (models.size() != 1) {
|
|
continue;
|
|
}
|
|
|
|
String[] texSplit = models.iterator().next().split(":");
|
|
String texture = texSplit[texSplit.length - 1];
|
|
|
|
textureFileName =
|
|
String.format(texturesDir, nameSpace, texture);
|
|
}
|
|
|
|
BufferedImage image = readImage(zipFile, textureFileName);
|
|
if (image == null) {
|
|
getLogger(TextureUtil.class).error("Cannot find {}", textureFileName);
|
|
continue;
|
|
}
|
|
int color = ImageUtil.getColor(image);
|
|
long distance = getDistance(image, color);
|
|
distanceMap.put(combined, (Long) distance);
|
|
colorMap.put(combined, (Integer) color);
|
|
}
|
|
Integer grass = null;
|
|
{
|
|
String grassFileName =
|
|
String.format(texturesDir, "minecraft", "grass_block_top");
|
|
BufferedImage image = readImage(zipFile, grassFileName);
|
|
if (image != null) {
|
|
grass = ImageUtil.getColor(image);
|
|
}
|
|
}
|
|
if (grass != null) {
|
|
// assets\minecraft\textures\colormap
|
|
ZipEntry grassEntry = getEntry(zipFile,
|
|
"assets/minecraft/textures/colormap/grass_block.png");
|
|
if (grassEntry != null) {
|
|
try (InputStream is = zipFile.getInputStream(grassEntry)) {
|
|
BufferedImage image = ImageIO.read(is);
|
|
// Update biome colors
|
|
for (BiomeColor biome : biomes) {
|
|
float adjTemp =
|
|
MathMan.clamp(biome.temperature, 0.0f, 1.0f);
|
|
float adjRainfall =
|
|
MathMan.clamp(biome.rainfall, 0.0f, 1.0f) * adjTemp;
|
|
int x = (int) (255 - adjTemp * 255);
|
|
int z = (int) (255 - adjRainfall * 255);
|
|
biome.grass = image.getRGB(x, z);
|
|
}
|
|
}
|
|
// swampland: perlin - avoid
|
|
biomes[6].grass = 0;
|
|
biomes[134].grass = 0;
|
|
// roofed forest: averaged w/ 0x28340A
|
|
biomes[29].grass =
|
|
multiplyColor(biomes[29].grass, 0x28340A + (255 << 24));
|
|
biomes[157].grass =
|
|
multiplyColor(biomes[157].grass, 0x28340A + (255 << 24));
|
|
// mesa : 0x90814D
|
|
biomes[37].grass = 0x90814D + (255 << 24);
|
|
biomes[38].grass = 0x90814D + (255 << 24);
|
|
biomes[39].grass = 0x90814D + (255 << 24);
|
|
biomes[165].grass = 0x90814D + (255 << 24);
|
|
biomes[166].grass = 0x90814D + (255 << 24);
|
|
biomes[167].grass = 0x90814D + (255 << 24);
|
|
List<BiomeColor> valid = new ArrayList<>();
|
|
for (BiomeColor biome : biomes) {
|
|
// biome.grass = multiplyColor(biome.grass, grass);
|
|
if (biome.grass != 0 && !biome.name
|
|
.equalsIgnoreCase("Unknown Biome")) {
|
|
valid.add(biome);
|
|
}
|
|
biome.grassCombined = multiplyColor(grass, biome.grass);
|
|
}
|
|
this.validBiomes = valid.toArray(new BiomeColor[0]);
|
|
|
|
ArrayList<BiomeColor> uniqueColors = new ArrayList<>();
|
|
Set<Integer> uniqueBiomesColors = new IntArraySet();
|
|
for (BiomeColor color : validBiomes) {
|
|
if (uniqueBiomesColors.add(color.grass)) {
|
|
uniqueColors.add(color);
|
|
}
|
|
}
|
|
int count = 0;
|
|
int count2 = 0;
|
|
uniqueBiomesColors.clear();
|
|
|
|
LongArrayList layerIds = new LongArrayList();
|
|
LongArrayList layerColors = new LongArrayList();
|
|
for (int i = 0; i < uniqueColors.size(); i++) {
|
|
for (int j = i; j < uniqueColors.size(); j++) {
|
|
for (int k = j; k < uniqueColors.size(); k++) {
|
|
BiomeColor c1 = uniqueColors.get(i);
|
|
BiomeColor c2 = uniqueColors.get(j);
|
|
BiomeColor c3 = uniqueColors.get(k);
|
|
int average =
|
|
averageColor(c1.grass, c2.grass, c3.grass);
|
|
if (uniqueBiomesColors.add(average)) {
|
|
count++;
|
|
layerColors.add((long) average);
|
|
layerIds.add(
|
|
(long) ((c1.id) + (c2.id << 8) + (c3.id
|
|
<< 16)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
validMixBiomeColors = new int[layerColors.size()];
|
|
for (int i = 0; i < layerColors.size(); i++) {
|
|
validMixBiomeColors[i] = (int) layerColors.getLong(i);
|
|
}
|
|
validMixBiomeIds = layerIds.toLongArray();
|
|
}
|
|
|
|
}
|
|
// Close the file
|
|
zipFile.close();
|
|
}
|
|
}
|
|
}
|
|
// Convert the color map to a simple array
|
|
validBlockIds = new int[colorMap.size()];
|
|
validColors = new int[colorMap.size()];
|
|
int index = 0;
|
|
for (Int2ObjectMap.Entry<Integer> entry : colorMap.int2ObjectEntrySet()) {
|
|
int combinedId = entry.getIntKey();
|
|
int color = entry.getValue();
|
|
blockColors[combinedId] = color;
|
|
validBlockIds[index] = combinedId;
|
|
validColors[index] = color;
|
|
index++;
|
|
}
|
|
ArrayList<Long> distances = new ArrayList<>(distanceMap.values());
|
|
Collections.sort(distances);
|
|
this.distances = new long[distances.size()];
|
|
for (int i = 0; i < this.distances.length; i++) {
|
|
this.distances[i] = distances.get(i);
|
|
}
|
|
for (Int2ObjectMap.Entry<Long> entry : distanceMap.int2ObjectEntrySet()) {
|
|
blockDistance[entry.getIntKey()] = entry.getValue();
|
|
}
|
|
calculateLayerArrays();
|
|
}
|
|
|
|
public int multiplyColor(int c1, int c2) {
|
|
int alpha1 = (c1 >> 24) & 0xFF;
|
|
int alpha2 = (c2 >> 24) & 0xFF;
|
|
int red1 = (c1 >> 16) & 0xFF;
|
|
int green1 = (c1 >> 8) & 0xFF;
|
|
int blue1 = (c1 >> 0) & 0xFF;
|
|
int red2 = (c2 >> 16) & 0xFF;
|
|
int green2 = (c2 >> 8) & 0xFF;
|
|
int blue2 = (c2 >> 0) & 0xFF;
|
|
int red = ((red1 * red2)) / 255;
|
|
int green = ((green1 * green2)) / 255;
|
|
int blue = ((blue1 * blue2)) / 255;
|
|
int alpha = ((alpha1 * alpha2)) / 255;
|
|
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
|
|
}
|
|
|
|
public int averageColor(int c1, int c2) {
|
|
int alpha1 = (c1 >> 24) & 0xFF;
|
|
int alpha2 = (c2 >> 24) & 0xFF;
|
|
int red1 = (c1 >> 16) & 0xFF;
|
|
int green1 = (c1 >> 8) & 0xFF;
|
|
int blue1 = (c1 >> 0) & 0xFF;
|
|
int red2 = (c2 >> 16) & 0xFF;
|
|
int green2 = (c2 >> 8) & 0xFF;
|
|
int blue2 = (c2 >> 0) & 0xFF;
|
|
int red = ((red1 + red2)) >> 1;
|
|
int green = ((green1 + green2)) >> 1;
|
|
int blue = ((blue1 + blue2)) >> 1;
|
|
int alpha = ((alpha1 + alpha2)) >> 1;
|
|
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
|
|
}
|
|
|
|
public int averageColor(int... colors) {
|
|
int alpha = 0;
|
|
int red = 0;
|
|
int green = 0;
|
|
int blue = 0;
|
|
for (int c : colors) {
|
|
alpha += (c >> 24) & 0xFF;
|
|
red += (c >> 16) & 0xFF;
|
|
green += (c >> 8) & 0xFF;
|
|
blue += (c >> 0) & 0xFF;
|
|
}
|
|
int num = colors.length;
|
|
alpha /= num;
|
|
red /= num;
|
|
green /= num;
|
|
blue /= num;
|
|
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
|
|
}
|
|
|
|
/**
|
|
* Assumes the top layer is a transparent color and the bottom is opaque
|
|
*/
|
|
public int combineTransparency(int top, int bottom) {
|
|
int alpha1 = (top >> 24) & 0xFF;
|
|
int alpha2 = 255 - alpha1;
|
|
int red1 = (top >> 16) & 0xFF;
|
|
int green1 = (top >> 8) & 0xFF;
|
|
int blue1 = (top >> 0) & 0xFF;
|
|
int red2 = (bottom >> 16) & 0xFF;
|
|
int green2 = (bottom >> 8) & 0xFF;
|
|
int blue2 = (bottom >> 0) & 0xFF;
|
|
int red = ((red1 * alpha1) + (red2 * alpha2)) / 255;
|
|
int green = ((green1 * alpha1) + (green2 * alpha2)) / 255;
|
|
int blue = ((blue1 * alpha1) + (blue2 * alpha2)) / 255;
|
|
return (red << 16) + (green << 8) + (blue << 0) + (255 << 24);
|
|
}
|
|
|
|
protected void calculateLayerArrays() {
|
|
Int2ObjectOpenHashMap<int[]> colorLayerMap = new Int2ObjectOpenHashMap<>();
|
|
for (int i = 0; i < validBlockIds.length; i++) {
|
|
int color = validColors[i];
|
|
int combined = validBlockIds[i];
|
|
if (hasAlpha(color)) {
|
|
for (int j = 0; j < validBlockIds.length; j++) {
|
|
int colorOther = validColors[j];
|
|
if (!hasAlpha(colorOther)) {
|
|
int combinedOther = validBlockIds[j];
|
|
int combinedColor = combineTransparency(color, colorOther);
|
|
colorLayerMap.put(combinedColor, new int[]{combined, combinedOther});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.validLayerColors = new int[colorLayerMap.size()];
|
|
this.validLayerBlocks = new int[colorLayerMap.size()][];
|
|
int index = 0;
|
|
for (Int2ObjectMap.Entry<int[]> entry : colorLayerMap.int2ObjectEntrySet()) {
|
|
validLayerColors[index] = entry.getIntKey();
|
|
validLayerBlocks[index++] = entry.getValue();
|
|
}
|
|
}
|
|
|
|
protected BlockType getNearestBlock(BlockType block, boolean darker) {
|
|
int color = getColor(block);
|
|
if (color == 0) {
|
|
return block;
|
|
}
|
|
BlockType darkerBlock = getNearestBlock(color, darker);
|
|
return darkerBlock != null ? darkerBlock : block;
|
|
}
|
|
|
|
protected BlockType getNearestBlock(int color, boolean darker) {
|
|
long min = Long.MAX_VALUE;
|
|
int closest = 0;
|
|
int red1 = (color >> 16) & 0xFF;
|
|
int green1 = (color >> 8) & 0xFF;
|
|
int blue1 = (color >> 0) & 0xFF;
|
|
int alpha = (color >> 24) & 0xFF;
|
|
int intensity1 = 2 * red1 + 4 * green1 + 3 * blue1;
|
|
for (int i = 0; i < validColors.length; i++) {
|
|
int other = validColors[i];
|
|
if (other != color && ((other >> 24) & 0xFF) == alpha) {
|
|
int red2 = (other >> 16) & 0xFF;
|
|
int green2 = (other >> 8) & 0xFF;
|
|
int blue2 = (other >> 0) & 0xFF;
|
|
int intensity2 = 2 * red2 + 4 * green2 + 3 * blue2;
|
|
if (darker ? intensity2 >= intensity1 : intensity1 >= intensity2) {
|
|
continue;
|
|
}
|
|
long distance = colorDistance(red1, green1, blue1, other);
|
|
if (distance < min) {
|
|
min = distance;
|
|
closest = validBlockIds[i];
|
|
}
|
|
}
|
|
}
|
|
if (min == Long.MAX_VALUE) {
|
|
return null;
|
|
}
|
|
return BlockTypes.get(closest);
|
|
}
|
|
|
|
private String getFileName(String path) {
|
|
String[] split = path.split("[/|\\\\]");
|
|
String name = split[split.length - 1];
|
|
int dot = name.indexOf('.');
|
|
if (dot != -1) {
|
|
name = name.substring(0, dot);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
private String alphabetize(String asset) {
|
|
String[] split = asset.split("_");
|
|
Arrays.sort(split);
|
|
return StringMan.join(split, "_");
|
|
}
|
|
|
|
protected boolean hasAlpha(int color) {
|
|
int alpha = (color >> 24) & 0xFF;
|
|
return alpha != 255;
|
|
}
|
|
|
|
protected long colorDistance(int red1, int green1, int blue1, int c2) {
|
|
int red2 = (c2 >> 16) & 0xFF;
|
|
int green2 = (c2 >> 8) & 0xFF;
|
|
int blue2 = (c2 >> 0) & 0xFF;
|
|
int rmean = (red1 + red2) >> 1;
|
|
int r = red1 - red2;
|
|
int g = green1 - green2;
|
|
int b = blue1 - blue2;
|
|
int hd = hueDistance(red1, green1, blue1, red2, green2, blue2);
|
|
return (((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8) + (hd
|
|
* hd);
|
|
}
|
|
|
|
public long getDistance(BufferedImage image, int c1) {
|
|
long totalDistSqr = 0;
|
|
int width = image.getWidth();
|
|
int height = image.getHeight();
|
|
int area = width * height;
|
|
int red1 = (c1 >> 16) & 0xFF;
|
|
int green1 = (c1 >> 8) & 0xFF;
|
|
int blue1 = (c1 >> 0) & 0xFF;
|
|
for (int x = 0; x < width; x++) {
|
|
for (int y = 0; y < height; y++) {
|
|
int c2 = image.getRGB(x, y);
|
|
long distance = colorDistance(red1, green1, blue1, c2);
|
|
totalDistSqr += distance * distance;
|
|
}
|
|
}
|
|
return totalDistSqr / area;
|
|
}
|
|
|
|
public int[] getValidBlockIds() {
|
|
return validBlockIds.clone();
|
|
}
|
|
|
|
public static class BiomeColor {
|
|
|
|
public int id;
|
|
public String name;
|
|
public float temperature;
|
|
public float rainfall;
|
|
public int grass;
|
|
public int grassCombined;
|
|
public int foliage;
|
|
|
|
public BiomeColor(int id, String name, float temperature, float rainfall, int grass,
|
|
int foliage) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.temperature = temperature;
|
|
this.rainfall = rainfall;
|
|
this.grass = grass;
|
|
this.grassCombined = grass;
|
|
this.foliage = foliage;
|
|
}
|
|
}
|
|
}
|