Move Clipboards to /tmp + Update upstream #3

Zusammengeführt
Lixfel hat 18 Commits von upstream nach main 2022-09-24 19:48:10 +02:00 zusammengeführt
21 geänderte Dateien mit 231 neuen und 108 gelöschten Zeilen

Datei anzeigen

@ -26,3 +26,23 @@ jobs:
files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar' files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar'
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
release-tag: ${{ github.event.release.tag_name }} release-tag: ${{ github.event.release.tag_name }}
- name: Upload release to CurseForge
uses: Kir-Antipov/mc-publish@v3.2
with:
curseforge-id: 103525
curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }}
files-primary: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar'
name: FastAsyncWorldEdit ${{ github.event.release.tag_name }}
version: ${{ github.event.release.tag_name }}
version-type: release
game-versions: |
1.19.1
1.19
1.18.2
1.18.1
1.18
1.17
1.16

Datei anzeigen

@ -23,7 +23,7 @@ logger.lifecycle("""
******************************************* *******************************************
""") """)
var rootVersion by extra("2.4.5") var rootVersion by extra("2.4.7")
var snapshot by extra("SNAPSHOT") var snapshot by extra("SNAPSHOT")
var revision: String by extra("") var revision: String by extra("")
var buildNumber by extra("") var buildNumber by extra("")

Datei anzeigen

@ -12,7 +12,7 @@ griefprevention = "16.18"
griefdefender = "2.1.0-SNAPSHOT" griefdefender = "2.1.0-SNAPSHOT"
mcore = "7.0.1" mcore = "7.0.1"
residence = "4.5._13.1" residence = "4.5._13.1"
towny = "0.98.3.5" towny = "0.98.3.8"
redprotect = "1.9.6" redprotect = "1.9.6"
# Third party # Third party
@ -38,7 +38,7 @@ text = "3.0.4"
piston = "0.5.7" piston = "0.5.7"
# Tests # Tests
mockito = "4.7.0" mockito = "4.8.0"
# Gradle plugins # Gradle plugins
pluginyml = "0.5.2" pluginyml = "0.5.2"

Datei anzeigen

@ -3,4 +3,4 @@ build:
- "./gradlew --stop" - "./gradlew --stop"
artifacts: artifacts:
"/binarys/FastAsyncWorldEdit-1.18.jar": "worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-2.4.5-SNAPSHOT.jar" "/binarys/FastAsyncWorldEdit-1.18.jar": "worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-2.4.7-SNAPSHOT.jar"

Datei anzeigen

@ -473,7 +473,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
static List<Entity> getEntities(LevelChunk chunk) { static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(new ChunkPos(chunk.locX, chunk.locZ)); return chunk.level.entityManager.getEntities(chunk.getPos());
} }
} }

Datei anzeigen

@ -79,6 +79,7 @@ import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.OptionalLong;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -217,10 +218,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
BiomeProvider biomeProvider = getBiomeProvider(); BiomeProvider biomeProvider = getBiomeProvider();
MinecraftServer server = originalServerWorld.getCraftServer().getServer(); MinecraftServer server = originalServerWorld.getCraftServer().getServer();
PrimaryLevelData levelProperties = (PrimaryLevelData) server.getWorldData(); WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent()
WorldGenSettings newOpts = levelProperties.worldGenSettings() ? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
.withSeed(originalWorldData.settings.hardcore(), options.getSeed()); : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld", "faweregentempworld",
originalWorldData.settings.gameType(), originalWorldData.settings.gameType(),

Datei anzeigen

@ -588,7 +588,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
static List<Entity> getEntities(LevelChunk chunk) { static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(new ChunkPos(chunk.locX, chunk.locZ)); return chunk.level.entityManager.getEntities(chunk.getPos());
} }
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> { record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {

Datei anzeigen

@ -213,10 +213,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
BiomeProvider biomeProvider = getBiomeProvider(); BiomeProvider biomeProvider = getBiomeProvider();
MinecraftServer server = originalServerWorld.getCraftServer().getServer(); MinecraftServer server = originalServerWorld.getCraftServer().getServer();
PrimaryLevelData levelProperties = (PrimaryLevelData) server.getWorldData(); WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
WorldGenSettings originalOpts = levelProperties.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent() WorldGenSettings newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) ? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld", "faweregentempworld",

Datei anzeigen

@ -585,23 +585,6 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
return true; return true;
} }
@Override
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
// Quickly add each entity to a list copy.
List<Entity> mcEntities = new ArrayList<>();
((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
List<org.bukkit.entity.Entity> list = new ArrayList<>();
mcEntities.forEach((mcEnt) -> {
org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity();
if (bukkitEntity.isValid()) {
list.add(bukkitEntity);
}
});
return list;
}
@Override @Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);

Datei anzeigen

@ -676,7 +676,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
for (UUID uuid : entityRemoves) { for (UUID uuid : entityRemoves) {
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid); Entity entity = nmsWorld.getEntities().get(uuid);
if (entity != null) { if (entity != null) {
removeEntity(entity); removeEntity(entity);
} }

Datei anzeigen

@ -278,20 +278,21 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
return; return;
} }
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ); ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
// UNLOADED_CHUNK LevelChunk levelChunk;
Optional<LevelChunk> optional = ((Either) chunkHolder
.getTickingChunkFuture()
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
// getChunkAtIfLoadedImmediately is paper only // getChunkAtIfLoadedImmediately is paper only
optional = optional.or(() -> Optional.ofNullable(nmsWorld levelChunk = nmsWorld
.getChunkSource() .getChunkSource()
.getChunkAtIfLoadedImmediately(chunkX, chunkZ))); .getChunkAtIfLoadedImmediately(chunkX, chunkZ);
} else {
levelChunk = ((Optional<LevelChunk>) ((Either) chunkHolder
.getTickingChunkFuture() // method is not present with new paper chunk system
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left())
.orElse(null);
} }
if (optional.isEmpty()) { if (levelChunk == null) {
return; return;
} }
LevelChunk levelChunk = optional.get();
TaskManager.taskManager().task(() -> { TaskManager.taskManager().task(() -> {
ClientboundLevelChunkWithLightPacket packet; ClientboundLevelChunkWithLightPacket packet;
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
@ -589,7 +590,10 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
static List<Entity> getEntities(LevelChunk chunk) { static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(new ChunkPos(chunk.locX, chunk.locZ)); if (PaperLib.isPaper()) {
return Arrays.asList(chunk.entities.getRawData());
}
return chunk.level.entityManager.getEntities(chunk.getPos());
} }
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> { record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {

Datei anzeigen

@ -214,10 +214,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
MinecraftServer server = originalServerWorld.getCraftServer().getServer(); MinecraftServer server = originalServerWorld.getCraftServer().getServer();
PrimaryLevelData levelProperties = (PrimaryLevelData) server.getWorldData(); WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
WorldGenSettings originalOpts = levelProperties.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent() WorldGenSettings newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) ? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld", "faweregentempworld",

Datei anzeigen

@ -110,7 +110,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
if (player != null && Settings.settings().CLIPBOARD.USE_DISK) { if (player != null && Settings.settings().CLIPBOARD.USE_DISK) {
BukkitPlayer cached = WorldEditPlugin.getInstance().getCachedPlayer(player); BukkitPlayer cached = WorldEditPlugin.getInstance().getCachedPlayer(player);
if (cached == null) { if (cached == null) {
loadClipboardFromDisk(); //loadClipboardFromDisk();
} }
} }
//FAWE end //FAWE end

Datei anzeigen

@ -141,10 +141,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public List<com.sk89q.worldedit.entity.Entity> getEntities(Region region) { public List<com.sk89q.worldedit.entity.Entity> getEntities(Region region) {
//FAWE start - allow async entity retrieval World world = getWorld();
List<Entity> ents = WorldEditPlugin.getInstance().getBukkitImplAdapter().getEntities(getWorld());
//FAWE end
List<Entity> ents = world.getEntities();
List<com.sk89q.worldedit.entity.Entity> entities = new ArrayList<>(); List<com.sk89q.worldedit.entity.Entity> entities = new ArrayList<>();
for (Entity ent : ents) { for (Entity ent : ents) {
if (region.contains(BukkitAdapter.asBlockVector(ent.getLocation()))) { if (region.contains(BukkitAdapter.asBlockVector(ent.getLocation()))) {
@ -157,9 +156,7 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public List<com.sk89q.worldedit.entity.Entity> getEntities() { public List<com.sk89q.worldedit.entity.Entity> getEntities() {
List<com.sk89q.worldedit.entity.Entity> list = new ArrayList<>(); List<com.sk89q.worldedit.entity.Entity> list = new ArrayList<>();
//FAWE start - allow async entity retrieval for (Entity entity : getWorld().getEntities()) {
for (Entity entity : WorldEditPlugin.getInstance().getBukkitImplAdapter().getEntities(getWorld())) {
//FAWE end
list.add(BukkitAdapter.adapt(entity)); list.add(BukkitAdapter.adapt(entity));
} }
return list; return list;

Datei anzeigen

@ -71,16 +71,25 @@ public class DiskOptimizedClipboard extends LinearClipboard {
private boolean canHaveBiomes = true; private boolean canHaveBiomes = true;
private int nbtBytesRemaining; private int nbtBytesRemaining;
private static File createTmpFile() {
File temp;
try {
temp = File.createTempFile("fawe", ".bd");
} catch (IOException e) {
throw new RuntimeException(e);
}
temp.deleteOnExit();
return temp;
}
/** /**
* Creates a new DiskOptimizedClipboard for the given region. Creates or overwrites a file using the given UUID as a name. * Creates a new DiskOptimizedClipboard for the given region. Creates or overwrites a file using the given UUID as a name.
*/ */
public DiskOptimizedClipboard(Region region, UUID uuid) { public DiskOptimizedClipboard(Region region, UUID uuid) {
this( this(
region.getDimensions(), region.getDimensions(),
MainUtil.getFile( createTmpFile()
Fawe.instance() != null ? Fawe.platform().getDirectory() : new File("."),
Settings.settings().PATHS.CLIPBOARD + File.separator + uuid + ".bd"
)
); );
setOffset(region.getMinimumPoint()); setOffset(region.getMinimumPoint());
setOrigin(region.getMinimumPoint()); setOrigin(region.getMinimumPoint());

Datei anzeigen

@ -66,7 +66,7 @@ public class SaturatePattern extends AbstractPattern {
} }
int newColor = TextureUtil.multiplyColor(currentColor, color); int newColor = TextureUtil.multiplyColor(currentColor, color);
BlockType newBlock = util.getNearestBlock(newColor); BlockType newBlock = util.getNearestBlock(newColor);
if (newBlock.equals(type)) { if (newBlock == null || newBlock.equals(type)) {
return false; return false;
} }
return set.setBlock(extent, newBlock.getDefaultState()); return set.setBlock(extent, newBlock.getDefaultState());

Datei anzeigen

@ -5,6 +5,9 @@ import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.filter.block.SingleFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.SingleFilterBlock;
import com.fastasyncworldedit.core.util.image.ImageUtil; import com.fastasyncworldedit.core.util.image.ImageUtil;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -24,19 +27,26 @@ import org.apache.logging.log4j.Logger;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.HexFormat;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -321,6 +331,8 @@ public class TextureUtil implements TextureHolder {
new BiomeColor(253, "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(254, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F)}; new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F)};
private static final String VERSION_MANIFEST = "https://piston-meta.mojang.com/mc/game/version_manifest.json";
private final BlockType[] layerBuffer = new BlockType[2]; private final BlockType[] layerBuffer = new BlockType[2];
protected int[] blockColors = new int[BlockTypes.size()]; protected int[] blockColors = new int[BlockTypes.size()];
protected long[] blockDistance = new long[BlockTypes.size()]; protected long[] blockDistance = new long[BlockTypes.size()];
@ -352,17 +364,43 @@ public class TextureUtil implements TextureHolder {
try { try {
LOGGER.info("Downloading asset jar from Mojang, please wait..."); LOGGER.info("Downloading asset jar from Mojang, please wait...");
new File(Fawe.platform().getDirectory() + "/" + Settings.settings().PATHS.TEXTURES + "/").mkdirs(); new File(Fawe.platform().getDirectory() + "/" + Settings.settings().PATHS.TEXTURES + "/").mkdirs();
try (BufferedInputStream in = new BufferedInputStream(
new URL("https://piston-data.mojang.com/v1/objects/c0898ec7c6a5a2eaa317770203a1554260699994/client.jar") try {
.openStream()); VersionMetadata metadata = getLatestVersion();
FileOutputStream fileOutputStream = new FileOutputStream( LOGGER.info("Latest release version is {}", metadata.version());
Fawe.platform().getDirectory() + "/" + Settings.settings().PATHS.TEXTURES + "/1.19.2.jar")) { HashedResource resource = getLatestClientJarUrl(metadata);
byte[] dataBuffer = new byte[1024];
int bytesRead; Path out = Path.of(
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) { Fawe.platform().getDirectory().getPath(),
fileOutputStream.write(dataBuffer, 0, bytesRead); Settings.settings().PATHS.TEXTURES,
metadata.version() + ".jar"
);
// Copy resource to local fs
try (final InputStream stream = new URL(resource.resource()).openStream();
final OutputStream writer = Files.newOutputStream(out)) {
stream.transferTo(writer);
} }
LOGGER.info("Asset jar down has been downloaded successfully."); // Validate sha-1 hash
try {
final String sha1 = calculateSha1(out);
if (!sha1.equals(resource.hash())) {
Files.deleteIfExists(out);
LOGGER.error(
"Hash comparison of final file failed (Expected: '{}', Calculated: '{}')",
resource.hash(), sha1
);
LOGGER.error("To prevent possibly malicious intentions, the downloaded file has been removed");
return;
}
} catch (NoSuchAlgorithmException e) {
LOGGER.warn("Couldn't verify integrity of downloaded client file");
LOGGER.warn(
"Please verify that the downloaded files '{}' hash is equal to '{}'",
out, resource.hash()
);
return;
}
LOGGER.info("Asset jar has been downloaded and validated successfully.");
} catch (IOException e) { } catch (IOException e) {
LOGGER.error( LOGGER.error(
"Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` " + "Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` " +
@ -388,7 +426,7 @@ public class TextureUtil implements TextureHolder {
HashSet<BlockType> blocks = new HashSet<>(); HashSet<BlockType> blocks = new HashSet<>();
for (int typeId = 0; typeId < ids.length; typeId++) { for (int typeId = 0; typeId < ids.length; typeId++) {
if (ids[typeId]) { if (ids[typeId]) {
blocks.add(BlockTypes.get(typeId)); blocks.add(BlockTypesCache.values[typeId]);
} }
} }
return fromBlocks(blocks); return fromBlocks(blocks);
@ -406,7 +444,7 @@ public class TextureUtil implements TextureHolder {
TextureUtil tu = Fawe.instance().getTextureUtil(); TextureUtil tu = Fawe.instance().getTextureUtil();
for (int typeId : tu.getValidBlockIds()) { for (int typeId : tu.getValidBlockIds()) {
BlockType block = BlockTypes.get(typeId); BlockType block = BlockTypesCache.values[typeId];
extent.init(0, 0, 0, block.getDefaultState().toBaseBlock()); extent.init(0, 0, 0, block.getDefaultState().toBaseBlock());
if (mask.test(extent)) { if (mask.test(extent)) {
blocks.add(block); blocks.add(block);
@ -555,6 +593,66 @@ public class TextureUtil implements TextureHolder {
return totalDistSqr / area; return totalDistSqr / area;
} }
/**
* Retrieves the minecraft versions manifest (containing all released versions) and returns the first {@code release}
* version (latest)
*
* @return {@link VersionMetadata} containing the id (= version) and url to the client manifest itself
* @throws IOException If any http / i/o operation fails.
* @since 2.4.6
*/
private static VersionMetadata getLatestVersion() throws IOException {
try (BufferedInputStream in = new BufferedInputStream(new URL(VERSION_MANIFEST).openStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
final JsonElement element = JsonParser.parseReader(reader);
for (final JsonElement versions : element.getAsJsonObject().getAsJsonArray("versions")) {
JsonObject version = versions.getAsJsonObject();
if (!version.get("type").getAsString().equals("release")) {
continue;
}
final String clientJsonUrl = version.get("url").getAsString();
final String id = version.get("id").getAsString();
return new VersionMetadata(id, clientJsonUrl);
}
}
throw new IOException("Failed to get latest version metadata");
}
/**
* Retrieves the url to the client.jar based on the previously retrieved {@link VersionMetadata}
*
* @param metadata The version metadata containing the url to the client.jar
* @return The full url to the client.jar including the expected file hash for validation purposes
* @throws IOException If any http / i/o operation fails.
* @since 2.4.6
*/
private static HashedResource getLatestClientJarUrl(VersionMetadata metadata) throws IOException {
try (BufferedInputStream in = new BufferedInputStream(new URL(metadata.url()).openStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
final JsonObject object = JsonParser.parseReader(reader).getAsJsonObject();
final JsonObject client = object.getAsJsonObject("downloads").getAsJsonObject("client");
return new HashedResource(client.get("url").getAsString(), client.get("sha1").getAsString());
}
}
/**
* Calculates the sha-1 hash based on the content of the provided file.
*
* @param path The path of the resource to generate the sha-1 hash for
* @return The hash of the file contents
* @throws NoSuchAlgorithmException If the SHA-1 algorithm could not be resolved
* @throws IOException If any I/O operation failed
* @since 2.4.6
*/
private static String calculateSha1(Path path) throws NoSuchAlgorithmException, IOException {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
try (final BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(path));
final DigestOutputStream digestOutputStream = new DigestOutputStream(OutputStream.nullOutputStream(), digest)) {
stream.transferTo(digestOutputStream);
return HexFormat.of().formatHex(digest.digest());
}
}
@Override @Override
public TextureUtil getTextureUtil() { public TextureUtil getTextureUtil() {
return this; return this;
@ -586,7 +684,7 @@ public class TextureUtil implements TextureHolder {
if (min == Long.MAX_VALUE) { if (min == Long.MAX_VALUE) {
return null; return null;
} }
return BlockTypes.get(closest); return BlockTypesCache.values[closest];
} }
/** /**
@ -615,7 +713,7 @@ public class TextureUtil implements TextureHolder {
if (min == Long.MAX_VALUE) { if (min == Long.MAX_VALUE) {
return null; return null;
} }
return BlockTypes.get(closest); return BlockTypesCache.values[closest];
} }
/** /**
@ -638,8 +736,8 @@ public class TextureUtil implements TextureHolder {
} }
} }
} }
layerBuffer[0] = BlockTypes.get(closest[0]); layerBuffer[0] = BlockTypesCache.values[closest[0]];
layerBuffer[1] = BlockTypes.get(closest[1]); layerBuffer[1] = BlockTypesCache.values[closest[1]];
return layerBuffer; return layerBuffer;
} }
@ -806,36 +904,25 @@ public class TextureUtil implements TextureHolder {
if (folder.exists()) { if (folder.exists()) {
// Get all the jar files // Get all the jar files
File[] files = folder.listFiles((dir, name) -> name.endsWith(".jar")); File[] files = folder.listFiles((dir, name) -> name.endsWith(".jar"));
if (files.length == 0) { // We expect the latest version to be already there, due to the download in TextureUtil#<init>
new File(Fawe.platform().getDirectory() + "/" + Settings.settings().PATHS.TEXTURES + "/") if (files == null || files.length == 0) {
.mkdirs(); LOGGER.error("No version jar found in {}. Delete the named folder and restart your server to download the " +
try (BufferedInputStream in = new BufferedInputStream( "missing assets.", folder.getPath());
new URL("https://piston-data.mojang.com/v1/objects/c0898ec7c6a5a2eaa317770203a1554260699994/client.jar") LOGGER.error(
.openStream()); "If no asset jar is created, please do so manually by creating a `FastAsyncWorldEdit/textures` " +
FileOutputStream fileOutputStream = new FileOutputStream( "folder with a `.minecraft/versions` jar or mods in it.");
Fawe.platform().getDirectory() + "/" + Settings.settings().PATHS.TEXTURES + "/1.19.2.jar")) {
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
fileOutputStream.close();
files = folder.listFiles((dir, name) -> name.endsWith(".jar"));
} catch (IOException e) {
LOGGER.error(
"Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` " +
"folder with a `.minecraft/versions` jar or mods in it.");
LOGGER.error("If the file exists, please make sure the server has read access to the directory.");
}
} }
if ((files.length > 0)) { if (files != null && (files.length > 0)) {
for (File file : files) { for (File file : files) {
ZipFile zipFile = new ZipFile(file); ZipFile zipFile = new ZipFile(file);
// Get all the groups in the current jar // Get all the groups in the current jar
// The vanilla textures are in `assets/minecraft` // The vanilla textures are in `assets/minecraft`
// A jar may contain textures for multiple mods // A jar may contain textures for multiple mods
String modelsDir = "assets/%1$s/models/block/%2$s.json"; String[] modelsDir = {
"assets/%1$s/models/block/%2$s.json",
"assets/%1$s/models/item/%2$s.json"
};
String texturesDir = "assets/%1$s/textures/%2$s.png"; String texturesDir = "assets/%1$s/textures/%2$s.png";
Type typeToken = new TypeToken<Map<String, Object>>() { Type typeToken = new TypeToken<Map<String, Object>>() {
@ -859,10 +946,15 @@ public class TextureUtil implements TextureHolder {
String nameSpace = split.length == 1 ? "" : split[0]; String nameSpace = split.length == 1 ? "" : split[0];
// Read models // Read models
String modelFileName = String.format(modelsDir, nameSpace, name); ZipEntry entry = null;
ZipEntry entry = getEntry(zipFile, modelFileName); for (final String dir : modelsDir) {
String modelFileName = String.format(dir, nameSpace, name);
if ((entry = getEntry(zipFile, modelFileName)) != null) {
break;
}
}
if (entry == null) { if (entry == null) {
LOGGER.error("Cannot find {} in {}", modelFileName, file); LOGGER.error("Cannot find {} in {}", modelsDir, file);
continue; continue;
} }
@ -1080,7 +1172,8 @@ public class TextureUtil implements TextureHolder {
if (min == Long.MAX_VALUE) { if (min == Long.MAX_VALUE) {
return null; return null;
} }
return BlockTypes.get(closest);
return BlockTypesCache.values[closest];
} }
private String getFileName(String path) { private String getFileName(String path) {
@ -1130,4 +1223,12 @@ public class TextureUtil implements TextureHolder {
} }
private record VersionMetadata(String version, String url) {
}
private record HashedResource(String resource, String hash) {
}
} }

Datei anzeigen

@ -455,7 +455,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
state = item.getType().getBlockType().getDefaultState(); state = item.getType().getBlockType().getDefaultState();
nbt = item.getNbtData(); nbt = item.getNbtData();
} else { } else {
BlockType type = BlockTypes.parse(typeString.toLowerCase(Locale.ROOT)); BlockType type = BlockTypes.parse(typeString.toLowerCase(Locale.ROOT), context);
if (type != null) { if (type != null) {
state = type.getDefaultState(); state = type.getDefaultState();

Datei anzeigen

@ -484,7 +484,12 @@ public class MCEditSchematicReader extends NBTSchematicReader {
} }
private BlockState getBlockState(int id, int data) { private BlockState getBlockState(int id, int data) {
return LegacyMapper.getInstance().getBlockFromLegacy(id, data); BlockState foundBlock = LegacyMapper.getInstance().getBlockFromLegacy(id, data);
if (foundBlock == null && data != 0) {
// Some schematics contain invalid data values, so try without the data value
return LegacyMapper.getInstance().getBlockFromLegacy(id, 0);
}
return foundBlock;
} }
@Override @Override

Datei anzeigen

@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.command.SuggestInputParseException;
import com.fastasyncworldedit.core.util.JoinedCharSequence; import com.fastasyncworldedit.core.util.JoinedCharSequence;
import com.fastasyncworldedit.core.util.StringMan; import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.world.registry.LegacyMapper; import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -1948,6 +1949,9 @@ public final class BlockTypes {
*/ */
public static BlockType parse(final String type) throws InputParseException { public static BlockType parse(final String type) throws InputParseException {
return parse(type, new ParserContext());
}
public static BlockType parse(final String type, final ParserContext context) throws InputParseException {
final String inputLower = type.toLowerCase(Locale.ROOT); final String inputLower = type.toLowerCase(Locale.ROOT);
String input = inputLower; String input = inputLower;
@ -1958,13 +1962,14 @@ public final class BlockTypes {
if (result != null) { if (result != null) {
return result; return result;
} }
if (context.isTryingLegacy()) {
try { try {
BlockStateHolder<BlockState> block = LegacyMapper.getInstance().getBlockFromLegacy(input); BlockStateHolder<BlockState> block = LegacyMapper.getInstance().getBlockFromLegacy(input);
if (block != null) { if (block != null) {
return block.getBlockType(); return block.getBlockType();
}
} catch (NumberFormatException | IndexOutOfBoundsException ignored) {
} }
} catch (NumberFormatException | IndexOutOfBoundsException ignored) {
} }
throw new SuggestInputParseException("Does not match a valid block type: " + inputLower, inputLower, () -> Stream.of( throw new SuggestInputParseException("Does not match a valid block type: " + inputLower, inputLower, () -> Stream.of(

Datei anzeigen

@ -28,7 +28,7 @@ dependencies {
}) })
api("org.apache.logging.log4j:log4j-api") api("org.apache.logging.log4j:log4j-api")
api("org.bstats:bstats-sponge:1.7") api("org.bstats:bstats-sponge:1.7")
testImplementation("org.mockito:mockito-core:4.7.0") testImplementation("org.mockito:mockito-core:4.8.0")
} }
<<<<<<< HEAD <<<<<<< HEAD