From ffe5f89afc0114fd61b22dc134e14ea4a9846969 Mon Sep 17 00:00:00 2001 From: TomyLobo Date: Mon, 24 Oct 2011 04:04:45 +0200 Subject: [PATCH] EditSession.flushQueue(): queueLast is now ordered with attachments in mind. --- .../java/com/sk89q/worldedit/EditSession.java | 64 ++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 955c5d176..5b8207913 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -18,6 +18,8 @@ */ package com.sk89q.worldedit; +import java.util.Deque; +import java.util.LinkedList; import java.util.Map; import java.util.HashMap; import java.util.LinkedHashMap; @@ -560,9 +562,67 @@ public class EditSession { // We don't want to place these blocks if other blocks were missing // because it might cause the items to drop if (blockBag == null || missingBlocks.size() == 0) { + final Set blocks = new HashSet(); + final Map blockTypes = new HashMap(); for (Map.Entry entry : queueLast) { - BlockVector pt = (BlockVector) entry.getKey(); - rawSetBlock(pt, (BaseBlock) entry.getValue()); + final BlockVector pt = entry.getKey(); + blocks.add(pt); + blockTypes.put(pt, entry.getValue()); + } + + while (!blocks.isEmpty()) { + BlockVector current = blocks.iterator().next(); + if (!blocks.contains(current)) { + continue; + } + + final Deque walked = new LinkedList(); + + while (true) { + walked.addFirst(current); + + assert(blockTypes.containsKey(current)); + + final BaseBlock baseBlock = blockTypes.get(current); + + final int type = baseBlock.getType(); + final int data = baseBlock.getData(); + + switch (type) { + case BlockID.WOODEN_DOOR: + case BlockID.IRON_DOOR: + if ((data & 0x8) == 0) { + // Deal with lower door halves being attached to the floor AND the upper half + BlockVector upperBlock = current.add(0, 1, 0).toBlockVector(); + if (blocks.contains(upperBlock) && !walked.contains(upperBlock)) { + walked.addFirst(upperBlock); + } + } + } + + final PlayerDirection attachment = BlockType.getAttachment(type, data); + if (attachment == null) { + // Block is not attached to anything => we can place it + break; + } + + current = current.add(attachment.vector()).toBlockVector(); + + if (!blocks.contains(current)) { + // We ran outside the remaing set => assume we can place blocks on this + break; + } + + if (walked.contains(current)) { + // Cycle detected => This will most likely go wrong, but there's nothing we can do about it. + break; + } + } + + for (BlockVector pt : walked) { + rawSetBlock(pt, blockTypes.get(pt)); + blocks.remove(pt); + } } }