Make core cross-version compatible

This commit is contained in:
Blue (Lukas Rieger) 2020-08-25 15:07:42 +02:00
parent 28d56e7374
commit 76ecb75e73
30 changed files with 362 additions and 138 deletions

View File

@ -55,6 +55,7 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
@ -72,12 +73,19 @@ public class BukkitPlugin extends JavaPlugin implements ServerInterface, Listene
public BukkitPlugin() {
Logger.global = new JavaLogger(getLogger());
MinecraftVersion version = MinecraftVersion.getLatest();
try {
version = MinecraftVersion.fromVersionString(Bukkit.getVersion());
} catch (IllegalArgumentException e) {
Logger.global.logWarning("Failed to find a matching version for version-string '" + Bukkit.getVersion() + "'! Using latest version: " + version.getVersionString());
}
this.onlinePlayerMap = new ConcurrentHashMap<>();
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
this.eventForwarder = new EventForwarder();
this.pluginInstance = new Plugin("bukkit", this);
this.pluginInstance = new Plugin(version, "bukkit", this);
this.commands = new BukkitCommands(this.pluginInstance);
BukkitPlugin.instance = this;

View File

@ -5,8 +5,7 @@
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
# and you agree that BlueMap will download and use a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA.
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
# %datetime-iso%

View File

@ -54,6 +54,7 @@
import de.bluecolored.bluemap.common.RenderManager;
import de.bluecolored.bluemap.common.RenderTask;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.config.WebServerConfig;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.render.hires.HiresModelManager;
@ -251,8 +252,21 @@ public static void main(String[] args) {
configFolder = new File(cmd.getOptionValue("c"));
configFolder.mkdirs();
}
//minecraft version
MinecraftVersion version = MinecraftVersion.getLatest();
if (cmd.hasOption("v")) {
String versionString = cmd.getOptionValue("v");
try {
version = MinecraftVersion.fromVersionString(versionString);
} catch (IllegalArgumentException e) {
Logger.global.logWarning("Could not determine a version from the provided version-string: '" + versionString + "'");
System.exit(1);
return;
}
}
blueMap = new BlueMapService(configFolder);
blueMap = new BlueMapService(version, configFolder);
boolean noActions = true;
if (cmd.hasOption("w")) {
@ -339,6 +353,15 @@ private static Options createOptions() {
.build()
);
options.addOption(
Option.builder("v")
.longOpt("mc-version")
.hasArg()
.argName("version")
.desc("Sets the minecraft-version, used e.g. to load resource-packs correctly. Defaults to the latest compatible version.")
.build()
);
options.addOption("w", "webserver", false, "Starts the web-server, configured in the 'webserver.conf' file");
options.addOption("g", "generate-webapp", false, "Generates the files for the web-app to the folder, configured in the 'render.conf' file (this is done automatically when rendering if the 'index.html' file in the webroot can't be found)");

View File

@ -5,8 +5,7 @@
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
# and you agree that BlueMap will download and use a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA.
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
# %datetime-iso%

View File

@ -26,6 +26,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -40,6 +41,7 @@
import de.bluecolored.bluemap.common.plugin.Plugin;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.config.ConfigManager;
import de.bluecolored.bluemap.core.config.CoreConfig;
import de.bluecolored.bluemap.core.config.MapConfig;
@ -62,6 +64,7 @@
* This is the attempt to generalize as many actions as possible to have CLI and Plugins run on the same general setup-code.
*/
public class BlueMapService {
private MinecraftVersion minecraftVersion;
private File configFolder;
private ThrowingFunction<File, UUID, IOException> worldUUIDProvider;
private ThrowingFunction<UUID, String, IOException> worldNameProvider;
@ -78,7 +81,8 @@ public class BlueMapService {
private Map<UUID, World> worlds;
private Map<String, MapType> maps;
public BlueMapService(File configFolder) {
public BlueMapService(MinecraftVersion minecraftVersion, File configFolder) {
this.minecraftVersion = minecraftVersion;
this.configFolder = configFolder;
Map<File, UUID> uuids = new HashMap<>();
@ -96,7 +100,8 @@ public BlueMapService(File configFolder) {
configManager = new ConfigManager();
}
public BlueMapService(ServerInterface serverInterface) {
public BlueMapService(MinecraftVersion minecraftVersion, ServerInterface serverInterface) {
this.minecraftVersion = minecraftVersion;
this.configFolder = serverInterface.getConfigFolder();
this.worldUUIDProvider = serverInterface::getUUIDForWorld;
this.worldNameProvider = serverInterface::getWorldName;
@ -166,7 +171,7 @@ private synchronized void loadWorldsAndMaps() throws IOException {
World world = worlds.get(worldUUID);
if (world == null) {
try {
world = MCAWorld.load(worldFolder.toPath(), worldUUID, getConfigManager().getBlockIdConfig(), getConfigManager().getBlockPropertiesConfig(), getConfigManager().getBiomeConfig(), worldNameProvider.apply(worldUUID), true);
world = MCAWorld.load(worldFolder.toPath(), worldUUID, minecraftVersion, getConfigManager().getBlockIdConfig(), getConfigManager().getBlockPropertiesConfig(), getConfigManager().getBiomeConfig(), worldNameProvider.apply(worldUUID), true);
worlds.put(worldUUID, world);
} catch (MissingResourcesException e) {
throw e; // rethrow this to stop loading and display resource-missing message
@ -215,8 +220,8 @@ private synchronized void loadWorldsAndMaps() throws IOException {
public synchronized ResourcePack getResourcePack() throws IOException, MissingResourcesException {
if (resourcePack == null) {
File defaultResourceFile = new File(getCoreConfig().getDataFolder(), "minecraft-client-" + ResourcePack.MINECRAFT_CLIENT_VERSION + ".jar");
File resourceExtensionsFile = new File(getCoreConfig().getDataFolder(), "resourceExtensions.zip");
File defaultResourceFile = new File(getCoreConfig().getDataFolder(), "minecraft-client-" + minecraftVersion.getVersionString() + ".jar");
File resourceExtensionsFile = new File(getCoreConfig().getDataFolder(), minecraftVersion.getResourcePrefix() + File.separator + "resourceExtensions.zip");
File textureExportFile = new File(getRenderConfig().getWebRoot(), "data" + File.separator + "textures.json");
@ -225,8 +230,8 @@ public synchronized ResourcePack getResourcePack() throws IOException, MissingRe
//download file
try {
Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + defaultResourceFile + " ...");
ResourcePack.downloadDefaultResource(defaultResourceFile);
Logger.global.logInfo("Downloading " + minecraftVersion.getClientDownloadUrl() + " to " + defaultResourceFile + " ...");
FileUtils.copyURLToFile(new URL(minecraftVersion.getClientDownloadUrl()), defaultResourceFile, 10000, 10000);
} catch (IOException e) {
throw new IOException("Failed to download resources!", e);
}
@ -253,7 +258,7 @@ public synchronized ResourcePack getResourcePack() throws IOException, MissingRe
resources.add(resourceExtensionsFile);
try {
resourcePack = new ResourcePack();
resourcePack = new ResourcePack(minecraftVersion);
if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile);
resourcePack.load(resources);
resourcePack.saveTextureFile(textureExportFile);

View File

@ -46,6 +46,7 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.common.plugin.skins.PlayerSkinUpdater;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.config.CoreConfig;
import de.bluecolored.bluemap.core.config.RenderConfig;
import de.bluecolored.bluemap.core.config.WebServerConfig;
@ -63,6 +64,7 @@ public class Plugin {
public static final String PLUGIN_ID = "bluemap";
public static final String PLUGIN_NAME = "BlueMap";
private MinecraftVersion minecraftVersion;
private String implementationType;
private ServerInterface serverInterface;
@ -83,7 +85,8 @@ public class Plugin {
private boolean loaded = false;
public Plugin(String implementationType, ServerInterface serverInterface) {
public Plugin(MinecraftVersion minecraftVersion, String implementationType, ServerInterface serverInterface) {
this.minecraftVersion = minecraftVersion;
this.implementationType = implementationType.toLowerCase();
this.serverInterface = serverInterface;
}
@ -92,7 +95,7 @@ public synchronized void load() throws IOException, ParseResourceException {
if (loaded) return;
unload(); //ensure nothing is left running (from a failed load or something)
blueMap = new BlueMapService(serverInterface);
blueMap = new BlueMapService(minecraftVersion, serverInterface);
//load configs
CoreConfig coreConfig = blueMap.getCoreConfig();

View File

@ -0,0 +1,79 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public enum MinecraftVersion {
MC_1_12 ("1.12", "mc1_12", "https://launcher.mojang.com/v1/objects/0f275bc1547d01fa5f56ba34bdc87d981ee12daf/client.jar"),
MC_1_13 ("1.13", "mc1_13", "https://launcher.mojang.com/v1/objects/30bfe37a8db404db11c7edf02cb5165817afb4d9/client.jar"),
MC_1_14 ("1.14", "mc1_13", "https://launcher.mojang.com/v1/objects/8c325a0c5bd674dd747d6ebaa4c791fd363ad8a9/client.jar"),
MC_1_15 ("1.15", "mc1_15", "https://launcher.mojang.com/v1/objects/e3f78cd16f9eb9a52307ed96ebec64241cc5b32d/client.jar"),
MC_1_16 ("1.16", "mc1_16", "https://launcher.mojang.com/v1/objects/653e97a2d1d76f87653f02242d243cdee48a5144/client.jar");
private static final Pattern VERSION_REGEX = Pattern.compile("(?:(?'major'\\d+)\\.(?'minor'\\d+))(?:\\.(?'patch'\\d+))?(?:\\-(?:pre|rc)\\d+)?");
private final String versionString;
private final String resourcePrefix;
private final String clientDownloadUrl;
MinecraftVersion(String versionString, String resourcePrefix, String clientDownloadUrl) {
this.versionString = versionString;
this.resourcePrefix = resourcePrefix;
this.clientDownloadUrl = clientDownloadUrl;
}
public String getVersionString() {
return this.versionString;
}
public String getResourcePrefix() {
return this.resourcePrefix;
}
public String getClientDownloadUrl() {
return this.clientDownloadUrl;
}
public static MinecraftVersion fromVersionString(String versionString) {
Matcher matcher = VERSION_REGEX.matcher(versionString);
if (!matcher.matches()) throw new IllegalArgumentException("Not a valid version string!");
String normalizedVersionString = matcher.group("major") + "." + matcher.group("minor");
for (MinecraftVersion mcv : values()) {
if (mcv.versionString.equals(normalizedVersionString)) return mcv;
}
throw new IllegalArgumentException("No matching version found!");
}
public static MinecraftVersion getLatest() {
return MC_1_16;
}
}

View File

@ -56,8 +56,6 @@ public class ConfigManager {
static {
CONFIG_PLACEHOLDERS.add(new Placeholder("version", BlueMap.VERSION));
CONFIG_PLACEHOLDERS.add(new Placeholder("datetime-iso", () -> LocalDateTime.now().withNano(0).toString()));
CONFIG_PLACEHOLDERS.add(new Placeholder("minecraft-client-url", ResourcePack.MINECRAFT_CLIENT_URL));
CONFIG_PLACEHOLDERS.add(new Placeholder("minecraft-client-version", ResourcePack.MINECRAFT_CLIENT_VERSION));
}
private BlockIdConfig blockIdConfig;

View File

@ -49,6 +49,7 @@
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.mca.extensions.BlockStateExtension;
import de.bluecolored.bluemap.core.mca.extensions.DoorExtension;
@ -81,25 +82,10 @@
public class MCAWorld implements World {
private static final Multimap<String, BlockStateExtension> BLOCK_STATE_EXTENSIONS = MultimapBuilder.hashKeys().arrayListValues().build();
static {
registerBlockStateExtension(new SnowyExtension());
registerBlockStateExtension(new StairShapeExtension());
registerBlockStateExtension(new FireExtension());
registerBlockStateExtension(new RedstoneExtension());
registerBlockStateExtension(new DoorExtension());
registerBlockStateExtension(new NetherFenceConnectExtension());
registerBlockStateExtension(new TripwireConnectExtension());
registerBlockStateExtension(new WallConnectExtension());
registerBlockStateExtension(new WoodenFenceConnectExtension());
registerBlockStateExtension(new GlassPaneConnectExtension());
registerBlockStateExtension(new DoublePlantExtension());
registerBlockStateExtension(new DoubleChestExtension());
}
private final UUID uuid;
private final Path worldFolder;
private final MinecraftVersion minecraftVersion;
private String name;
private int seaLevel;
private Vector3i spawnPoint;
@ -109,6 +95,8 @@ public class MCAWorld implements World {
private BlockIdMapper blockIdMapper;
private BlockPropertiesMapper blockPropertiesMapper;
private BiomeMapper biomeMapper;
private final Multimap<String, BlockStateExtension> blockStateExtensions;
private boolean ignoreMissingLightData;
@ -117,6 +105,7 @@ public class MCAWorld implements World {
private MCAWorld(
Path worldFolder,
UUID uuid,
MinecraftVersion minecraftVersion,
String name,
int worldHeight,
int seaLevel,
@ -128,6 +117,7 @@ private MCAWorld(
) {
this.uuid = uuid;
this.worldFolder = worldFolder;
this.minecraftVersion = minecraftVersion;
this.name = name;
this.seaLevel = seaLevel;
this.spawnPoint = spawnPoint;
@ -140,6 +130,20 @@ private MCAWorld(
this.forgeBlockMappings = new HashMap<>();
this.blockStateExtensions = MultimapBuilder.hashKeys().arrayListValues().build();
registerBlockStateExtension(new SnowyExtension(minecraftVersion));
registerBlockStateExtension(new StairShapeExtension());
registerBlockStateExtension(new FireExtension());
registerBlockStateExtension(new RedstoneExtension());
registerBlockStateExtension(new DoorExtension(minecraftVersion));
registerBlockStateExtension(new NetherFenceConnectExtension());
registerBlockStateExtension(new TripwireConnectExtension());
registerBlockStateExtension(new WallConnectExtension());
registerBlockStateExtension(new WoodenFenceConnectExtension(minecraftVersion));
registerBlockStateExtension(new GlassPaneConnectExtension());
registerBlockStateExtension(new DoublePlantExtension(minecraftVersion));
registerBlockStateExtension(new DoubleChestExtension());
this.chunkCache = Caffeine.newBuilder()
.maximumSize(500)
.expireAfterWrite(1, TimeUnit.MINUTES)
@ -186,7 +190,7 @@ private BlockState getExtendedBlockState(Chunk chunk, Vector3i pos) {
BlockState blockState = chunk.getBlockState(pos);
if (chunk instanceof ChunkAnvil112) { // only use extensions if old format chunk (1.12) in the new format block-states are saved with extensions
for (BlockStateExtension ext : BLOCK_STATE_EXTENSIONS.get(blockState.getFullId())) {
for (BlockStateExtension ext : blockStateExtensions.get(blockState.getFullId())) {
blockState = ext.extend(this, pos, blockState);
}
}
@ -386,6 +390,10 @@ public String getForgeBlockIdMapping(int id) {
return forgeBlockMappings.get(id);
}
public MinecraftVersion getMinecraftVersion() {
return minecraftVersion;
}
private Path getRegionFolder() {
return worldFolder.resolve("region");
}
@ -394,11 +402,17 @@ private Path getMCAFilePath(Vector2i region) {
return getRegionFolder().resolve(MCAUtil.createNameFromRegionLocation(region.getX(), region.getY()));
}
public static MCAWorld load(Path worldFolder, UUID uuid, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper) throws IOException {
return load(worldFolder, uuid, blockIdMapper, blockPropertiesMapper, biomeIdMapper, null, false);
private void registerBlockStateExtension(BlockStateExtension extension) {
for (String id : extension.getAffectedBlockIds()) {
this.blockStateExtensions.put(id, extension);
}
}
public static MCAWorld load(Path worldFolder, UUID uuid, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper, String name, boolean ignoreMissingLightData) throws IOException {
public static MCAWorld load(Path worldFolder, UUID uuid, MinecraftVersion version, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper) throws IOException {
return load(worldFolder, uuid, version, blockIdMapper, blockPropertiesMapper, biomeIdMapper, null, false);
}
public static MCAWorld load(Path worldFolder, UUID uuid, MinecraftVersion version, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper, String name, boolean ignoreMissingLightData) throws IOException {
try {
boolean subDimension = false;
@ -430,6 +444,7 @@ public static MCAWorld load(Path worldFolder, UUID uuid, BlockIdMapper blockIdMa
MCAWorld world = new MCAWorld(
worldFolder,
uuid,
version,
name,
worldHeight,
seaLevel,
@ -483,10 +498,4 @@ public static Vector2i chunkToRegion(Vector2i pos) {
);
}
public static void registerBlockStateExtension(BlockStateExtension extension) {
for (String id : extension.getAffectedBlockIds()) {
BLOCK_STATE_EXTENSIONS.put(id, extension);
}
}
}

View File

@ -24,7 +24,7 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
@ -35,6 +35,6 @@ public interface BlockStateExtension {
BlockState extend(MCAWorld world, Vector3i pos, BlockState state);
Collection<String> getAffectedBlockIds();
Set<String> getAffectedBlockIds();
}

View File

@ -24,28 +24,48 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.util.Direction;
import de.bluecolored.bluemap.core.world.BlockState;
public class DoorExtension implements BlockStateExtension {
private static final Collection<String> AFFECTED_BLOCK_IDS = Lists.newArrayList(
"minecraft:oak_door",
"minecraft:iron_door",
"minecraft:spruce_door",
"minecraft:birch_door",
"minecraft:jungle_door",
"minecraft:acacia_door",
"minecraft:dark_oak_door"
);
private final Set<String> affectedBlockIds;
public DoorExtension(MinecraftVersion version) {
switch (version) {
case MC_1_12:
affectedBlockIds = Sets.newHashSet(
"minecraft:wooden_door",
"minecraft:iron_door",
"minecraft:spruce_door",
"minecraft:birch_door",
"minecraft:jungle_door",
"minecraft:acacia_door",
"minecraft:dark_oak_door"
);
break;
default:
affectedBlockIds = Sets.newHashSet(
"minecraft:oak_door",
"minecraft:iron_door",
"minecraft:spruce_door",
"minecraft:birch_door",
"minecraft:jungle_door",
"minecraft:acacia_door",
"minecraft:dark_oak_door"
);
break;
}
}
@Override
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
@ -76,8 +96,8 @@ public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
}
@Override
public Collection<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
public Set<String> getAffectedBlockIds() {
return affectedBlockIds;
}
}

View File

@ -24,10 +24,10 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.util.Direction;
@ -35,7 +35,7 @@
public class DoubleChestExtension implements BlockStateExtension {
private static final Collection<String> AFFECTED_BLOCK_IDS = Lists.newArrayList(
private static final Set<String> AFFECTED_BLOCK_IDS = Sets.newHashSet(
"minecraft:chest",
"minecraft:trapped_chest"
);
@ -54,7 +54,7 @@ public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
}
@Override
public Collection<String> getAffectedBlockIds() {
public Set<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
}

View File

@ -24,26 +24,40 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.util.Direction;
import de.bluecolored.bluemap.core.world.BlockState;
public class DoublePlantExtension implements BlockStateExtension {
private static final Collection<String> AFFECTED_BLOCK_IDS = Lists.newArrayList(
"minecraft:sunflower",
"minecraft:lilac",
"minecraft:tall_grass",
"minecraft:large_fern",
"minecraft:rose_bush",
"minecraft:peony"
);
private final Set<String> affectedBlockIds;
public DoublePlantExtension(MinecraftVersion version) {
switch (version) {
case MC_1_12:
affectedBlockIds = Sets.newHashSet(
"minecraft:double_plant"
);
break;
default:
affectedBlockIds = Sets.newHashSet(
"minecraft:sunflower",
"minecraft:lilac",
"minecraft:tall_grass",
"minecraft:large_fern",
"minecraft:rose_bush",
"minecraft:peony"
);
break;
}
}
@Override
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
@ -57,8 +71,8 @@ public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
}
@Override
public Collection<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
public Set<String> getAffectedBlockIds() {
return affectedBlockIds;
}
}

View File

@ -24,10 +24,10 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.util.Direction;
@ -35,7 +35,7 @@
public class FireExtension implements BlockStateExtension {
private static final Collection<String> AFFECTED_BLOCK_IDS = Lists.newArrayList(
private static final Set<String> AFFECTED_BLOCK_IDS = Sets.newHashSet(
"minecraft:fire"
);
@ -60,7 +60,7 @@ public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
}
@Override
public Collection<String> getAffectedBlockIds() {
public Set<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
}

View File

@ -24,11 +24,9 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.mca.MCAWorld;
@ -37,7 +35,7 @@
public class RedstoneExtension implements BlockStateExtension {
private static final Collection<String> AFFECTED_BLOCK_IDS = Lists.newArrayList(
private static final Set<String> AFFECTED_BLOCK_IDS = Sets.newHashSet(
"minecraft:redstone_wire"
);
@ -90,7 +88,7 @@ private String connection(MCAWorld world, Vector3i pos, boolean upBlocking, Dire
}
@Override
public Collection<String> getAffectedBlockIds() {
public Set<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
}

View File

@ -24,26 +24,48 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.world.BlockState;
public class SnowyExtension implements BlockStateExtension {
private static final Collection<String> AFFECTED_BLOCK_IDS = Lists.newArrayList(
"minecraft:grass_block",
"minecraft:podzol"
);
private final Set<String> affectedBlockIds;
private final String snowLayerId;
private final String snowBlockId;
public SnowyExtension(MinecraftVersion version) {
switch (version) {
case MC_1_12:
affectedBlockIds = Sets.newHashSet(
"minecraft:grass",
"minecraft:mycelium"
);
snowLayerId = "minecraft:snow_layer";
snowBlockId = "minecraft:snow";
break;
default:
affectedBlockIds = Sets.newHashSet(
"minecraft:grass_block",
"minecraft:podzol"
);
snowLayerId = "minecraft:snow";
snowBlockId = "minecraft:snow_block";
break;
}
}
@Override
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
BlockState above = world.getBlockState(pos.add(0, 1, 0));
if (above.getFullId().equals("minecraft:snow") || above.getFullId().equals("minecraft:snow_block")) {
if (above.getFullId().equals(snowLayerId) || above.getFullId().equals(snowBlockId)) {
return state.with("snowy", "true");
} else {
return state.with("snowy", "false");
@ -51,8 +73,8 @@ public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
}
@Override
public Collection<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
public Set<String> getAffectedBlockIds() {
return affectedBlockIds;
}
}

View File

@ -24,8 +24,7 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.Sets;
@ -36,7 +35,7 @@
public class StairShapeExtension implements BlockStateExtension {
private static final HashSet<String> AFFECTED_BLOCK_IDS = Sets.newHashSet(
private static final Set<String> AFFECTED_BLOCK_IDS = Sets.newHashSet(
"minecraft:oak_stairs",
"minecraft:cobblestone_stairs",
"minecraft:brick_stairs",
@ -112,7 +111,7 @@ private boolean isEqualStairs(BlockState stair1, BlockState stair2) {
}
@Override
public Collection<String> getAffectedBlockIds() {
public Set<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
}

View File

@ -24,25 +24,44 @@
*/
package de.bluecolored.bluemap.core.mca.extensions;
import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.Sets;
public class WoodenFenceConnectExtension extends ConnectSameOrFullBlockExtension {
import de.bluecolored.bluemap.core.MinecraftVersion;
private static final HashSet<String> AFFECTED_BLOCK_IDS = Sets.newHashSet(
"minecraft:oak_fence",
"minecraft:spruce_fence",
"minecraft:birch_fence",
"minecraft:jungle_fence",
"minecraft:dark_oak_fence",
"minecraft:acacia_fence"
);
public class WoodenFenceConnectExtension extends ConnectSameOrFullBlockExtension {
private final Set<String> affectedBlockIds;
public WoodenFenceConnectExtension(MinecraftVersion version) {
switch (version) {
case MC_1_12:
affectedBlockIds = Sets.newHashSet(
"minecraft:fence",
"minecraft:spruce_fence",
"minecraft:birch_fence",
"minecraft:jungle_fence",
"minecraft:dark_oak_fence",
"minecraft:acacia_fence"
);
break;
default:
affectedBlockIds = Sets.newHashSet(
"minecraft:oak_fence",
"minecraft:spruce_fence",
"minecraft:birch_fence",
"minecraft:jungle_fence",
"minecraft:dark_oak_fence",
"minecraft:acacia_fence"
);
break;
}
}
@Override
public Set<String> getAffectedBlockIds() {
return AFFECTED_BLOCK_IDS;
return affectedBlockIds;
}
}

View File

@ -42,12 +42,23 @@
public class HiresModelRenderer {
private final String grassId;
private RenderSettings renderSettings;
private BlockStateModelFactory modelFactory;
public HiresModelRenderer(ResourcePack resourcePack, RenderSettings renderSettings) {
this.renderSettings = renderSettings;
this.modelFactory = new BlockStateModelFactory(resourcePack, renderSettings);
switch (resourcePack.getMinecraftVersion()) {
case MC_1_12:
grassId = "minecraft:tall_grass";
break;
default:
grassId = "minecraft:grass";
break;
}
}
public HiresModel render(WorldTile tile, AABB region) {
@ -91,7 +102,7 @@ public HiresModel render(WorldTile tile, AABB region) {
color = MathUtils.overlayColors(blockModel.getMapColor(), color);
//TODO: quick hack to random offset grass
if (block.getBlockState().getFullId().equals("minecraft:grass")){
if (block.getBlockState().getFullId().equals(grassId)){
float dx = (MathUtils.hashToFloat(x, y, z, 123984) - 0.5f) * 0.75f;
float dz = (MathUtils.hashToFloat(x, y, z, 345542) - 0.5f) * 0.75f;
blockModel.translate(new Vector3f(dx, 0, dz));

View File

@ -74,7 +74,7 @@ private BlockStateModel createModel(Block block, BlockState blockState) throws N
BlockStateModel model = new BlockStateModel();
BlockColorCalculator colorCalculator = resourcePack.getBlockColorCalculator();
ResourceModelBuilder modelBuilder = new ResourceModelBuilder(block, renderSettings, colorCalculator);
LiquidModelBuilder liquidBuilder = new LiquidModelBuilder(block, blockState, renderSettings, colorCalculator);
LiquidModelBuilder liquidBuilder = new LiquidModelBuilder(block, blockState, resourcePack.getMinecraftVersion(), renderSettings, colorCalculator);
for (TransformedBlockModelResource bmr : resource.getModels(blockState, block.getPosition())){
switch (bmr.getModel().getType()){

View File

@ -32,6 +32,7 @@
import com.flowpowered.math.vector.Vector4f;
import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.model.ExtendedFace;
import de.bluecolored.bluemap.core.model.ExtendedModel;
import de.bluecolored.bluemap.core.render.RenderSettings;
@ -58,10 +59,11 @@ public class LiquidModelBuilder {
private BlockState liquidBlockState;
private Block block;
private MinecraftVersion minecraftVersion;
private RenderSettings renderSettings;
private BlockColorCalculator colorCalculator;
public LiquidModelBuilder(Block block, BlockState liquidBlockState, RenderSettings renderSettings, BlockColorCalculator colorCalculator) {
public LiquidModelBuilder(Block block, BlockState liquidBlockState, MinecraftVersion minecraftVersion, RenderSettings renderSettings, BlockColorCalculator colorCalculator) {
this.block = block;
this.renderSettings = renderSettings;
this.liquidBlockState = liquidBlockState;
@ -106,7 +108,7 @@ public BlockStateModel build(BlockModelResource bmr) {
int textureId = texture.getId();
Vector3f tintcolor = Vector3f.ONE;
if (liquidBlockState.getFullId().equals("minecraft:water")) {
if (minecraftVersion != MinecraftVersion.MC_1_12 && liquidBlockState.getFullId().equals("minecraft:water")) {
tintcolor = colorCalculator.getWaterAverageColor(block);
}

View File

@ -390,7 +390,10 @@ private Face buildFace(Element element, Direction direction, ConfigurationNode n
String dirString = node.getNode("cullface").getString();
if (dirString.equals("bottom")) dirString = "down";
if (dirString.equals("top")) dirString = "up";
face.cullface = Direction.fromString(dirString);
try {
face.cullface = Direction.fromString(dirString);
} catch (IllegalArgumentException ignore) {}
}
return face;

View File

@ -181,6 +181,9 @@ public BlockStateResource build(String blockstateFile) throws IOException {
String conditionString = entry.getKey().toString();
ConfigurationNode transformedModelNode = entry.getValue();
//some exceptions in 1.12 resource packs that we ignore
if (conditionString.equals("all") || conditionString.equals("map")) continue;
Variant variant = blockState.new Variant();
variant.condition = parseConditionString(conditionString);
variant.models = loadModels(transformedModelNode, blockstateFile, null);
@ -242,8 +245,17 @@ private Weighted<TransformedBlockModelResource> loadModel(ConfigurationNode node
String namespacedModelPath = node.getNode("model").getString();
if (namespacedModelPath == null)
throw new ParseResourceException("No model defined!");
String modelPath = ResourcePack.namespacedToAbsoluteResourcePath(namespacedModelPath, "models") + ".json";
String modelPath;
switch (resourcePack.getMinecraftVersion()) {
case MC_1_12:
modelPath = ResourcePack.namespacedToAbsoluteResourcePath(namespacedModelPath, "models/block") + ".json";
break;
default:
modelPath = ResourcePack.namespacedToAbsoluteResourcePath(namespacedModelPath, "models") + ".json";
break;
}
BlockModelResource model = resourcePack.blockModelResources.get(modelPath);
if (model == null) {

View File

@ -30,7 +30,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@ -42,6 +41,7 @@
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.BlockStateResource.Builder;
import de.bluecolored.bluemap.core.resourcepack.fileaccess.BluemapAssetOverrideFileAccess;
@ -54,9 +54,6 @@
* Represents all resources (BlockStates / BlockModels and Textures) that are loaded and used to generate map-models.
*/
public class ResourcePack {
public static final String MINECRAFT_CLIENT_VERSION = "1.16.1";
public static final String MINECRAFT_CLIENT_URL = "https://launcher.mojang.com/v1/objects/c9abbe8ee4fa490751ca70635340b7cf00db83ff/client.jar";
private static final String[] CONFIG_FILES = {
"blockColors.json",
@ -65,6 +62,8 @@ public class ResourcePack {
"biomes.json"
};
private MinecraftVersion minecraftVersion;
protected Map<String, BlockStateResource> blockStateResources;
protected Map<String, BlockModelResource> blockModelResources;
protected TextureGallery textures;
@ -76,7 +75,9 @@ public class ResourcePack {
private Multimap<String, Resource> configs;
public ResourcePack() {
public ResourcePack(MinecraftVersion minecraftVersion) {
this.minecraftVersion = minecraftVersion;
blockStateResources = new HashMap<>();
blockModelResources = new HashMap<>();
textures = new TextureGallery();
@ -210,15 +211,8 @@ public BlockColorCalculator getBlockColorCalculator() {
return blockColorCalculator;
}
/**
* Synchronously downloads the default minecraft resources from the mojang-servers.
* @param file The file to save the downloaded resources to
* @throws IOException If an IOException occurs during the download
*/
public static void downloadDefaultResource(File file) throws IOException {
if (file.exists()) file.delete();
file.getParentFile().mkdirs();
org.apache.commons.io.FileUtils.copyURLToFile(new URL(MINECRAFT_CLIENT_URL), file, 10000, 10000);
public MinecraftVersion getMinecraftVersion() {
return minecraftVersion;
}
protected static String namespacedToAbsoluteResourcePath(String namespacedPath, String resourceTypeFolder) {

View File

@ -45,6 +45,7 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
import de.bluecolored.bluemap.fabric.events.PlayerJoinCallback;
@ -78,7 +79,7 @@ public FabricMod() {
this.onlinePlayerMap = new ConcurrentHashMap<>();
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
pluginInstance = new Plugin("fabric", this);
pluginInstance = new Plugin(MinecraftVersion.MC_1_16, "fabric", this);
this.worldUUIDs = new ConcurrentHashMap<>();
this.eventForwarder = new FabricEventForwarder(this);

View File

@ -5,8 +5,7 @@
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
# and you agree that BlueMap will download and use a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA.
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
# %datetime-iso%

View File

@ -45,6 +45,7 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
import net.minecraft.entity.player.PlayerEntity;
@ -82,7 +83,7 @@ public ForgeMod() {
this.onlinePlayerMap = new ConcurrentHashMap<>();
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
this.pluginInstance = new Plugin("forge", this);
this.pluginInstance = new Plugin(MinecraftVersion.MC_1_16, "forge", this);
this.worldUUIDs = new ConcurrentHashMap<>();
this.eventForwarder = new ForgeEventForwarder(this);

View File

@ -5,8 +5,7 @@
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
# and you agree that BlueMap will download and use a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA.
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
# %datetime-iso%

View File

@ -57,6 +57,7 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.MinecraftVersion;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
import de.bluecolored.bluemap.sponge.SpongeCommands.SpongeCommandProxy;
@ -95,7 +96,14 @@ public SpongePlugin(org.slf4j.Logger logger) {
this.onlinePlayerMap = new ConcurrentHashMap<>();
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
this.pluginInstance = new Plugin("sponge", this);
MinecraftVersion version = MinecraftVersion.MC_1_12;
try {
version = MinecraftVersion.fromVersionString(Sponge.getPlatform().getMinecraftVersion().getName());
} catch (IllegalArgumentException e) {
Logger.global.logWarning("Failed to find a matching version for version-name '" + Sponge.getPlatform().getMinecraftVersion().getName() + "'! Using latest known sponge-version: " + version.getVersionString());
}
this.pluginInstance = new Plugin(version, "sponge", this);
this.commands = new SpongeCommands(pluginInstance);
}

View File

@ -5,8 +5,7 @@
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
# and you agree that BlueMap will download and use a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA.
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
# %datetime-iso%