Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-25 18:40:05 +01:00
Add more schematic compat, cleanup.
Dieser Commit ist enthalten in:
Ursprung
bfc1fd8fd0
Commit
526b3366b5
@ -34,7 +34,9 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.EntityNBTCompatibilityHandler;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.FlowerPotCompatibilityHandler;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NoteBlockCompatibilityHandler;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.Pre13HangingCompatibilityHandler;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.SignCompatibilityHandler;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -63,8 +65,10 @@ public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
|
||||
private static final ImmutableList<NBTCompatibilityHandler> COMPATIBILITY_HANDLERS
|
||||
= ImmutableList.of(
|
||||
new SignCompatibilityHandler()
|
||||
// TODO Add a handler for skulls, flower pots, note blocks, etc.
|
||||
new SignCompatibilityHandler(),
|
||||
new FlowerPotCompatibilityHandler(),
|
||||
new NoteBlockCompatibilityHandler()
|
||||
// TODO - skulls, item tags for inventories...? DFUs :>
|
||||
);
|
||||
private static final ImmutableList<EntityNBTCompatibilityHandler> ENTITY_COMPATIBILITY_HANDLERS
|
||||
= ImmutableList.of(
|
||||
@ -167,65 +171,54 @@ public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
// Need to pull out tile entities
|
||||
List<Tag> tileEntities = requireTag(schematic, "TileEntities", ListTag.class).getValue();
|
||||
Map<BlockVector3, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
|
||||
Map<BlockVector3, BlockState> blockOverrides = new HashMap<>();
|
||||
|
||||
for (Tag tag : tileEntities) {
|
||||
if (!(tag instanceof CompoundTag)) continue;
|
||||
CompoundTag t = (CompoundTag) tag;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
int x = t.getInt("x");
|
||||
int y = t.getInt("y");
|
||||
int z = t.getInt("z");
|
||||
String id = t.getString("id");
|
||||
|
||||
Map<String, Tag> values = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, Tag> entry : t.getValue().entrySet()) {
|
||||
switch (entry.getKey()) {
|
||||
case "x":
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
x = ((IntTag) entry.getValue()).getValue();
|
||||
}
|
||||
break;
|
||||
case "y":
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
y = ((IntTag) entry.getValue()).getValue();
|
||||
}
|
||||
break;
|
||||
case "z":
|
||||
if (entry.getValue() instanceof IntTag) {
|
||||
z = ((IntTag) entry.getValue()).getValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
Map<String, Tag> values = new HashMap<>(t.getValue());
|
||||
values.put("id", new StringTag(convertBlockEntityId(id)));
|
||||
|
||||
int index = y * width * length + z * width + x;
|
||||
BlockState block = LegacyMapper.getInstance().getBlockFromLegacy(blocks[index], blockData[index]);
|
||||
if (block != null) {
|
||||
BlockState newBlock = block;
|
||||
if (newBlock != null) {
|
||||
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
|
||||
if (handler.isAffectedBlock(block)) {
|
||||
handler.updateNBT(block, values);
|
||||
if (handler.isAffectedBlock(newBlock)) {
|
||||
newBlock = handler.updateNBT(block, values);
|
||||
if (newBlock == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockVector3 vec = BlockVector3.at(x, y, z);
|
||||
tileEntitiesMap.put(vec, values);
|
||||
if (newBlock != block) {
|
||||
blockOverrides.put(vec, newBlock);
|
||||
}
|
||||
}
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(origin);
|
||||
|
||||
// Don't log a torrent of errors
|
||||
int failedBlockSets = 0;
|
||||
|
||||
for (int x = 0; x < width; ++x) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int z = 0; z < length; ++z) {
|
||||
int index = y * width * length + z * width + x;
|
||||
BlockVector3 pt = BlockVector3.at(x, y, z);
|
||||
BlockState state = LegacyMapper.getInstance().getBlockFromLegacy(blocks[index], blockData[index]);
|
||||
boolean useOverride = blockOverrides.containsKey(pt);
|
||||
BlockState state = useOverride
|
||||
? blockOverrides.get(pt)
|
||||
: LegacyMapper.getInstance().getBlockFromLegacy(blocks[index], blockData[index]);
|
||||
|
||||
try {
|
||||
if (state != null) {
|
||||
@ -235,20 +228,11 @@ public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
clipboard.setBlock(region.getMinimumPoint().add(pt), state);
|
||||
}
|
||||
} else {
|
||||
log.warn("Unknown block when pasting schematic: " + blocks[index] + ":" + blockData[index] + ". Please report this issue.");
|
||||
if (!useOverride) {
|
||||
log.warn("Unknown block when pasting schematic: " + blocks[index] + ":" + blockData[index] + ". Please report this issue.");
|
||||
}
|
||||
}
|
||||
} catch (WorldEditException e) {
|
||||
switch (failedBlockSets) {
|
||||
case 0:
|
||||
log.warn("Failed to set block on a Clipboard", e);
|
||||
break;
|
||||
case 1:
|
||||
log.warn("Failed to set block on a Clipboard (again) -- no more messages will be logged", e);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
failedBlockSets++;
|
||||
} catch (WorldEditException ignored) { // BlockArrayClipboard won't throw this
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -258,8 +242,9 @@ public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
// Entities
|
||||
// ====================================================================
|
||||
|
||||
List<Tag> entityTags = getTag(schematic, "Entities", ListTag.class).getValue();
|
||||
if (entityTags != null) {
|
||||
ListTag entityList = getTag(schematic, "Entities", ListTag.class);
|
||||
if (entityList != null) {
|
||||
List<Tag> entityTags = entityList.getValue();
|
||||
for (Tag tag : entityTags) {
|
||||
if (tag instanceof CompoundTag) {
|
||||
CompoundTag compound = (CompoundTag) tag;
|
||||
@ -289,32 +274,66 @@ public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
|
||||
private String convertEntityId(String id) {
|
||||
switch(id) {
|
||||
case "xp_orb":
|
||||
return "experience_orb";
|
||||
case "xp_bottle":
|
||||
return "experience_bottle";
|
||||
case "eye_of_ender_signal":
|
||||
return "eye_of_ender";
|
||||
case "ender_crystal":
|
||||
return "end_crystal";
|
||||
case "fireworks_rocket":
|
||||
return "firework_rocket";
|
||||
case "commandblock_minecart":
|
||||
return "command_block_minecart";
|
||||
case "snowman":
|
||||
return "snow_golem";
|
||||
case "villager_golem":
|
||||
return "iron_golem";
|
||||
case "evocation_fangs":
|
||||
return "evoker_fangs";
|
||||
case "evocation_illager":
|
||||
return "evoker";
|
||||
case "vindication_illager":
|
||||
return "vindicator";
|
||||
case "illusion_illager":
|
||||
return "illusioner";
|
||||
case "AreaEffectCloud": return "area_effect_cloud";
|
||||
case "ArmorStand": return "armor_stand";
|
||||
case "CaveSpider": return "cave_spider";
|
||||
case "MinecartChest": return "chest_minecart";
|
||||
case "MinecartCommandBlock": return "commandblock_minecart";
|
||||
case "DragonFireball": return "dragon_fireball";
|
||||
case "ThrownEgg": return "egg";
|
||||
case "EnderCrystal": return "ender_crystal";
|
||||
case "EnderDragon": return "ender_dragon";
|
||||
case "ThrownEnderpearl": return "ender_pearl";
|
||||
case "EyeOfEnderSignal": return "eye_of_ender_signal";
|
||||
case "FallingSand": return "falling_block";
|
||||
case "FireworksRocketEntity": return "fireworks_rocket";
|
||||
case "MinecartFurnace": return "furnace_minecart";
|
||||
case "MinecartHopper": return "hopper_minecart";
|
||||
case "EntityHorse": return "horse";
|
||||
case "ItemFrame": return "item_frame";
|
||||
case "LeashKnot": return "leash_knot";
|
||||
case "LightningBolt": return "lightning_bolt";
|
||||
case "LavaSlime": return "magma_cube";
|
||||
case "MinecartRideable": return "minecart";
|
||||
case "MushroomCow": return "mooshroom";
|
||||
case "Ozelot": return "ocelot";
|
||||
case "PolarBear": return "polar_bear";
|
||||
case "ThrownPotion": return "potion";
|
||||
case "ShulkerBullet": return "shulker_bullet";
|
||||
case "SmallFireball": return "small_fireball";
|
||||
case "MinecartSpawner": return "spawner_minecart";
|
||||
case "SpectralArrow": return "spectral_arrow";
|
||||
case "PrimedTnt": return "tnt";
|
||||
case "MinecartTNT": return "tnt_minecart";
|
||||
case "VillagerGolem": return "villager_golem";
|
||||
case "WitherBoss": return "wither";
|
||||
case "WitherSkull": return "wither_skull";
|
||||
case "ThrownExpBottle": return "xp_bottle";
|
||||
case "XPOrb": return "xp_orb";
|
||||
case "PigZombie": return "zombie_pigman";
|
||||
default: return id;
|
||||
}
|
||||
}
|
||||
|
||||
private String convertBlockEntityId(String id) {
|
||||
switch(id) {
|
||||
case "Cauldron": return "brewing_stand";
|
||||
case "Control": return "command_block";
|
||||
case "DLDetector": return "daylight_detector";
|
||||
case "Trap": return "dispenser";
|
||||
case "EnchantTable": return "enchanting_table";
|
||||
case "EndGateway": return "end_gateway";
|
||||
case "AirPortal": return "end_portal";
|
||||
case "EnderChest": return "ender_chest";
|
||||
case "FlowerPot": return "flower_pot";
|
||||
case "RecordPlayer": return "jukebox";
|
||||
case "MobSpawner": return "mob_spawner";
|
||||
case "Music":
|
||||
case "noteblock":
|
||||
return "note_block";
|
||||
case "Structure": return "structure_block";
|
||||
default: return id;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,74 @@
|
||||
package com.sk89q.worldedit.extent.clipboard.io.legacycompat;
|
||||
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class FlowerPotCompatibilityHandler implements NBTCompatibilityHandler {
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean isAffectedBlock(B block) {
|
||||
return block.getBlockType() == BlockTypes.FLOWER_POT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
|
||||
Tag item = values.get("Item");
|
||||
if (item instanceof StringTag) {
|
||||
String id = ((StringTag) item).getValue();
|
||||
int data = 0;
|
||||
Tag dataTag = values.get("Data");
|
||||
if (dataTag instanceof IntTag) {
|
||||
data = ((IntTag) dataTag).getValue();
|
||||
}
|
||||
BlockState newState = convertLegacyBlockType(id, data);
|
||||
if (newState != null) {
|
||||
return (B) newState; // generics pls :\
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
private BlockState convertLegacyBlockType(String id, int data) {
|
||||
int newId = 0;
|
||||
switch (id) {
|
||||
case "minecraft:red_flower":
|
||||
newId = 38; // now poppy
|
||||
break;
|
||||
case "minecraft:yellow_flower":
|
||||
newId = 37; // now dandelion
|
||||
break;
|
||||
case "minecraft:sapling":
|
||||
newId = 6; // oak_sapling
|
||||
break;
|
||||
case "minecraft:deadbush":
|
||||
case "minecraft:tallgrass":
|
||||
newId = 31; // dead_bush with fern and grass (not 32!)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
String plantedName = null;
|
||||
if (newId == 0) {
|
||||
plantedName = id.substring(10);
|
||||
} else {
|
||||
BlockState plantedWithData = LegacyMapper.getInstance().getBlockFromLegacy(newId, data);
|
||||
if (plantedWithData != null) {
|
||||
plantedName = plantedWithData.getBlockType().getId().substring(10); // remove "minecraft:"
|
||||
}
|
||||
}
|
||||
if (plantedName != null) {
|
||||
BlockType potAndPlanted = BlockTypes.get("minecraft:potted_" + plantedName);
|
||||
if (potAndPlanted != null) {
|
||||
return potAndPlanted.getDefaultState();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -26,5 +26,5 @@ import java.util.Map;
|
||||
|
||||
public interface NBTCompatibilityHandler {
|
||||
<B extends BlockStateHolder<B>> boolean isAffectedBlock(B block);
|
||||
<B extends BlockStateHolder<B>> void updateNBT(B block, Map<String, Tag> values);
|
||||
<B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values);
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
package com.sk89q.worldedit.extent.clipboard.io.legacycompat;
|
||||
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.registry.state.IntegerProperty;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler {
|
||||
private static final IntegerProperty NoteProperty;
|
||||
|
||||
static {
|
||||
IntegerProperty temp;
|
||||
try {
|
||||
temp = (IntegerProperty) (Property<?>) BlockTypes.NOTE_BLOCK.getProperty("note");
|
||||
} catch (NullPointerException | IllegalArgumentException | ClassCastException e) {
|
||||
temp = null;
|
||||
}
|
||||
NoteProperty = temp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean isAffectedBlock(B block) {
|
||||
return NoteProperty != null && block.getBlockType() == BlockTypes.NOTE_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
|
||||
// note that instrument was note stored (in state or nbt) previously.
|
||||
// it will be updated to the block below when it gets set into the world for the first time
|
||||
Tag noteTag = values.get("note");
|
||||
if (noteTag instanceof ByteTag) {
|
||||
Byte note = ((ByteTag) noteTag).getValue();
|
||||
if (note != null) {
|
||||
return (B) block.with(NoteProperty, (int) note);
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
}
|
@ -30,30 +30,32 @@ public class Pre13HangingCompatibilityHandler implements EntityNBTCompatibilityH
|
||||
|
||||
@Override
|
||||
public boolean isAffectedEntity(EntityType type, CompoundTag tag) {
|
||||
boolean hasLegacyDirection = tag.containsKey("Dir");
|
||||
if (!type.getId().startsWith("minecraft:")) {
|
||||
return false;
|
||||
}
|
||||
boolean hasLegacyDirection = tag.containsKey("Dir") || tag.containsKey("Direction");
|
||||
boolean hasFacing = tag.containsKey("Facing");
|
||||
return hasLegacyDirection || hasFacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag updateNBT(EntityType type, CompoundTag tag) {
|
||||
boolean hasLegacyDirection = tag.containsKey("Dir");
|
||||
boolean hasFacing = tag.containsKey("Facing");
|
||||
int d;
|
||||
if (hasLegacyDirection) {
|
||||
d = MCDirections.fromLegacyHanging((byte) tag.asInt("Dir"));
|
||||
boolean hasLegacyDir = tag.containsKey("Dir");
|
||||
boolean hasLegacyDirection = tag.containsKey("Direction");
|
||||
boolean hasPre113Facing = tag.containsKey("Facing");
|
||||
Direction newDirection;
|
||||
if (hasLegacyDir) {
|
||||
newDirection = MCDirections.fromPre13Hanging(MCDirections.fromLegacyHanging((byte) tag.asInt("Dir")));
|
||||
} else if (hasLegacyDirection) {
|
||||
newDirection = MCDirections.fromPre13Hanging(tag.asInt("Direction"));
|
||||
} else if (hasPre113Facing) {
|
||||
newDirection = MCDirections.fromPre13Hanging(tag.asInt("Facing"));
|
||||
} else {
|
||||
d = tag.asInt("Facing");
|
||||
return tag;
|
||||
}
|
||||
|
||||
Direction newDirection = MCDirections.fromPre13Hanging(d);
|
||||
|
||||
byte hangingByte = (byte) MCDirections.toHanging(newDirection);
|
||||
|
||||
CompoundTagBuilder builder = tag.createBuilder();
|
||||
builder.putByte("Direction", hangingByte);
|
||||
builder.putByte("Facing", hangingByte);
|
||||
builder.putByte("Dir", MCDirections.toLegacyHanging(MCDirections.toHanging(newDirection)));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ public class SignCompatibilityHandler implements NBTCompatibilityHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> void updateNBT(B block, Map<String, Tag> values) {
|
||||
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
String key = "Text" + (i + 1);
|
||||
Tag value = values.get(key);
|
||||
@ -69,5 +69,6 @@ public class SignCompatibilityHandler implements NBTCompatibilityHandler {
|
||||
values.put("Text" + (i + 1), new StringTag(jsonTextObject.toString()));
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
@ -130,8 +130,6 @@ public class ExtentEntityCopy implements EntityFunction {
|
||||
if (tag != null) {
|
||||
// Handle hanging entities (paintings, item frames, etc.)
|
||||
boolean hasTilePosition = tag.containsKey("TileX") && tag.containsKey("TileY") && tag.containsKey("TileZ");
|
||||
boolean hasDirection = tag.containsKey("Direction");
|
||||
boolean hasLegacyDirection = tag.containsKey("Dir");
|
||||
boolean hasFacing = tag.containsKey("Facing");
|
||||
|
||||
if (hasTilePosition) {
|
||||
@ -143,26 +141,15 @@ public class ExtentEntityCopy implements EntityFunction {
|
||||
.putInt("TileY", newTilePosition.getBlockY())
|
||||
.putInt("TileZ", newTilePosition.getBlockZ());
|
||||
|
||||
if (hasDirection || hasLegacyDirection || hasFacing) {
|
||||
Direction direction;
|
||||
if (hasDirection) {
|
||||
direction = MCDirections.fromPre13Hanging(tag.asInt("Direction"));
|
||||
} else if (hasLegacyDirection) {
|
||||
direction = MCDirections.fromPre13Hanging(
|
||||
MCDirections.fromLegacyHanging((byte) tag.asInt("Dir"))
|
||||
);
|
||||
} else {
|
||||
direction = MCDirections.fromHanging(tag.asInt("Facing"));
|
||||
}
|
||||
if (hasFacing) {
|
||||
Direction direction = MCDirections.fromHanging(tag.asInt("Facing"));
|
||||
|
||||
if (direction != null) {
|
||||
Vector3 vector = transform.apply(direction.toVector()).subtract(transform.apply(Vector3.ZERO)).normalize();
|
||||
Direction newDirection = Direction.findClosest(vector, Flag.CARDINAL);
|
||||
|
||||
if (newDirection != null) {
|
||||
builder.putByte("Direction", (byte) MCDirections.toPre13Hanging(newDirection));
|
||||
builder.putByte("Facing", (byte) MCDirections.toHanging(newDirection));
|
||||
builder.putByte("Dir", MCDirections.toLegacyHanging(MCDirections.toHanging(newDirection)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,21 +82,6 @@ public final class MCDirections {
|
||||
}
|
||||
}
|
||||
|
||||
public static int toPre13Hanging(Direction direction) {
|
||||
switch (direction) {
|
||||
case SOUTH:
|
||||
return 0;
|
||||
case WEST:
|
||||
return 1;
|
||||
case NORTH:
|
||||
return 2;
|
||||
case EAST:
|
||||
return 3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int fromLegacyHanging(byte i) {
|
||||
switch (i) {
|
||||
case 0: return 2;
|
||||
@ -106,15 +91,6 @@ public final class MCDirections {
|
||||
}
|
||||
}
|
||||
|
||||
public static byte toLegacyHanging(int i) {
|
||||
switch (i) {
|
||||
case 0: return (byte) 2;
|
||||
case 1: return (byte) 1;
|
||||
case 2: return (byte) 0;
|
||||
default: return (byte) 3;
|
||||
}
|
||||
}
|
||||
|
||||
public static Direction fromRotation(int i) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren