Fixed issue #43: Duplicating blocks in survival (undo/redo not working in normal mode).

Fixed QuickReplace in normal mode not placing any blocks.
Fixed blockstates sometimes changing on undo/redo.
Now clearing UndoRedo stacks on clientside when changing dimension or logging out.
Breaking mirror/array in survival is now possible again.
Breaking blocks in survival in any buildmode is now possible (previously only in normal mode unless instabreaking was enabled). Still with limited (vanilla) reach.
This commit is contained in:
Christian Knaapen
2019-07-09 02:11:32 +02:00
parent 11cd20c3d3
commit 3921a0b70b
8 changed files with 257 additions and 60 deletions

View File

@@ -93,11 +93,20 @@ public class EffortlessBuilding
EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 3, Side.CLIENT); EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 3, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 4, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 4, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 4, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(CancelModeMessage.MessageHandler.class, CancelModeMessage.class, 5, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(CancelModeMessage.MessageHandler.class, CancelModeMessage.class, 5, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(CancelModeMessage.MessageHandler.class, CancelModeMessage.class, 5, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(RequestLookAtMessage.MessageHandler.class, RequestLookAtMessage.class, 6, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(RequestLookAtMessage.MessageHandler.class, RequestLookAtMessage.class, 6, Side.CLIENT); EffortlessBuilding.packetHandler.registerMessage(RequestLookAtMessage.MessageHandler.class, RequestLookAtMessage.class, 6, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(AddUndoMessage.MessageHandler.class, AddUndoMessage.class, 7, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(AddUndoMessage.MessageHandler.class, AddUndoMessage.class, 7, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(ClearUndoMessage.MessageHandler.class, ClearUndoMessage.class, 8, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(ClearUndoMessage.MessageHandler.class, ClearUndoMessage.class, 8, Side.CLIENT);
proxy.preInit(event); proxy.preInit(event);
} }

View File

@@ -5,6 +5,7 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@@ -30,6 +31,9 @@ import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.AddUndoMessage;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.ClearUndoMessage;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage; import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
import scala.actors.threadpool.Arrays; import scala.actors.threadpool.Arrays;
@@ -96,13 +100,15 @@ public class EventHandler
} else if (modifierSettings.doQuickReplace()) { } else if (modifierSettings.doQuickReplace()) {
//Cancel event and send message if QuickReplace //Cancel event and send message if QuickReplace
event.setCanceled(true); event.setCanceled(true);
EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState(), true), (EntityPlayerMP) player); EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(true), (EntityPlayerMP) player);
EffortlessBuilding.packetHandler.sendTo(new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()), (EntityPlayerMP) player);
} else { } else {
//NORMAL mode, let vanilla handle block placing //NORMAL mode, let vanilla handle block placing
//But modifiers should still work //But modifiers should still work
//Send message to client, which sends message back with raytrace info //Send message to client, which sends message back with raytrace info
EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState(), false), (EntityPlayerMP) player); EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(false), (EntityPlayerMP) player);
EffortlessBuilding.packetHandler.sendTo(new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()), (EntityPlayerMP) player);
} }
} }
@@ -117,9 +123,12 @@ public class EventHandler
event.setCanceled(true); event.setCanceled(true);
} else { } else {
//NORMAL mode, let vanilla handle block breaking //NORMAL mode, let vanilla handle block breaking
//But modifiers and QuickReplace should still work //But modifiers should still work
//Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work //Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work
BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false); BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false);
//Add to undo stack in client
EffortlessBuilding.packetHandler.sendTo(new AddUndoMessage(event.getPos(), event.getState(), Blocks.AIR.getDefaultState()), (EntityPlayerMP) event.getPlayer());
} }
} }
@@ -169,8 +178,11 @@ public class EventHandler
@SubscribeEvent @SubscribeEvent
public static void onPlayerLoggedOut(PlayerLoggedOutEvent event) { public static void onPlayerLoggedOut(PlayerLoggedOutEvent event) {
UndoRedo.clear(event.player); EntityPlayer player = event.player;
//TODO call clientside if (player.getEntityWorld().isRemote) return;
UndoRedo.clear(player);
EffortlessBuilding.packetHandler.sendTo(new ClearUndoMessage(), (EntityPlayerMP) player);
} }
@SubscribeEvent @SubscribeEvent
@@ -183,10 +195,12 @@ public class EventHandler
@SubscribeEvent @SubscribeEvent
public static void onPlayerChangedDimension(PlayerChangedDimensionEvent event) { public static void onPlayerChangedDimension(PlayerChangedDimensionEvent event) {
EntityPlayer player = event.player; EntityPlayer player = event.player;
if (player.getEntityWorld().isRemote) return;
ModifierSettingsManager.handleNewPlayer(player); ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player); ModeSettingsManager.handleNewPlayer(player);
UndoRedo.clear(event.player); UndoRedo.clear(event.player);
//TODO call clientside EffortlessBuilding.packetHandler.sendTo(new ClearUndoMessage(), (EntityPlayerMP) player);
} }
} }

View File

@@ -122,6 +122,11 @@ public class BuildModes {
//Use a network message to break blocks in the distance using clientside mouse input //Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) { public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null; BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null;
//Early out if cant break far, coming from own mouse event (not block broken event)
//To make breaking blocks in survival possible without breaking instantly
if (!ReachHelper.canBreakFar(player)) return;
onBlockBroken(player, startPos, true); onBlockBroken(player, startPos, true);
} }
@@ -135,16 +140,20 @@ public class BuildModes {
return; return;
} }
if (!ReachHelper.canBreakFar(player)) return;
//If first click //If first click
if (currentlyBreaking.get(player) == null) { if (currentlyBreaking.get(player) == null) {
//If startpos is null, dont do anything //If startpos is null, dont do anything
if (startPos == null) return; if (startPos == null) return;
} }
//Get coordinates ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Early out if cant break far and (if in normal mode) no modifier is enabled
//So either cant break far and you are not in normal mode or cant break far and you are in normal mode, but no modifier is enabled
// if (!ReachHelper.canBreakFar(player) && (breakStartPos || !BuildModifiers.isEnabled(modifierSettings, startPos))) return;
//Get coordinates
BuildModeEnum buildMode = modeSettings.getBuildMode(); BuildModeEnum buildMode = modeSettings.getBuildMode();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, EnumFacing.UP, Vec3d.ZERO, true); List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, EnumFacing.UP, Vec3d.ZERO, true);

View File

@@ -3,6 +3,7 @@ package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
@@ -75,10 +76,19 @@ public class BuildModifiers {
} }
} }
//add to undo stack //Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work
BlockPos firstPos = startCoordinates.get(0); //(Block is placed by the time it gets here, and unplaced after this)
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.getDefaultState());
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
//If all new blockstates are air then no use in adding it, no block was actually placed
//Can happen when e.g. placing one block in yourself
if (Collections.frequency(newBlockStates, Blocks.AIR.getDefaultState()) != newBlockStates.size()) {
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
}
} }
public static void onBlockBroken(EntityPlayer player, List<BlockPos> startCoordinates, boolean breakStartPos) { public static void onBlockBroken(EntityPlayer player, List<BlockPos> startCoordinates, boolean breakStartPos) {
@@ -100,7 +110,7 @@ public class BuildModifiers {
//list of air blockstates //list of air blockstates
for (BlockPos coordinate : coordinates) { for (BlockPos coordinate : coordinates) {
newBlockStates.add(Block.getBlockById(0).getDefaultState()); newBlockStates.add(Blocks.AIR.getDefaultState());
} }
} else { } else {
@@ -125,6 +135,10 @@ public class BuildModifiers {
} }
} }
//Set first newBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block isn't broken yet by the time it gets here, and broken after this)
if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.getDefaultState());
//add to undo stack //add to undo stack
BlockPos firstPos = startCoordinates.get(0); BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);

View File

@@ -3,6 +3,7 @@ package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -31,17 +32,36 @@ public class UndoRedo {
public static void addUndo(EntityPlayer player, BlockSet blockSet) { public static void addUndo(EntityPlayer player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer; Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
//Assert coordinates is as long as previous and new blockstate lists
if (blockSet.getCoordinates().size() != blockSet.getPreviousBlockStates().size() ||
blockSet.getCoordinates().size() != blockSet.getNewBlockStates().size()) {
EffortlessBuilding.logger.error("Coordinates and blockstate lists are not equal length. Coordinates: {}. Previous blockstates: {}. New blockstates: {}.",
blockSet.getCoordinates().size(), blockSet.getPreviousBlockStates().size(), blockSet.getNewBlockStates().size());
}
//Warn if previous and new blockstate are equal
//Can happen in a lot of valid cases
// for (int i = 0; i < blockSet.getCoordinates().size(); i++) {
// if (blockSet.getPreviousBlockStates().get(i).equals(blockSet.getNewBlockStates().get(i))) {
// EffortlessBuilding.logger.warn("Previous and new blockstates are equal at index {}. Blockstate: {}.",
// i, blockSet.getPreviousBlockStates().get(i));
// }
// }
//If no stack exists, make one //If no stack exists, make one
if (!undoStacks.containsKey(player.getUniqueID())) { if (!undoStacks.containsKey(player.getUniqueID())) {
undoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize])); undoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize]));
} }
undoStacks.get(player.getUniqueID()).push(blockSet); undoStacks.get(player.getUniqueID()).push(blockSet);
} }
private static void addRedo(EntityPlayer player, BlockSet blockSet) { private static void addRedo(EntityPlayer player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer; Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
//(No asserts necessary, it's private)
//If no stack exists, make one //If no stack exists, make one
if (!redoStacks.containsKey(player.getUniqueID())) { if (!redoStacks.containsKey(player.getUniqueID())) {
redoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize])); redoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize]));
@@ -76,10 +96,12 @@ public class UndoRedo {
BlockPos coordinate = coordinates.get(i); BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i); ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack //get blockstate from itemstack
IBlockState previousBlockState = Block.getBlockById(0).getDefaultState(); IBlockState previousBlockState = Blocks.AIR.getDefaultState();
if (itemStack.getItem() instanceof ItemBlock) { if (itemStack.getItem() instanceof ItemBlock) {
previousBlockState = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); previousBlockState = previousBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} }
if (player.world.isBlockLoaded(coordinate, true)) { if (player.world.isBlockLoaded(coordinate, true)) {
@@ -88,7 +110,9 @@ public class UndoRedo {
itemStack = findItemStackInInventory(player, previousBlockStates.get(i)); itemStack = findItemStackInInventory(player, previousBlockStates.get(i));
//get blockstate from new itemstack //get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) { if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) {
previousBlockState = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); previousBlockState = previousBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} else {
previousBlockState = Blocks.AIR.getDefaultState();
} }
} }
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true); if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true);
@@ -115,6 +139,7 @@ public class UndoRedo {
BlockSet blockSet = redoStack.pop(); BlockSet blockSet = redoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates(); List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<IBlockState> newBlockStates = blockSet.getNewBlockStates(); List<IBlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec(); Vec3d hitVec = blockSet.getHitVec();
@@ -127,16 +152,25 @@ public class UndoRedo {
//place blocks //place blocks
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i); BlockPos coordinate = coordinates.get(i);
IBlockState newBlockState = newBlockStates.get(i);
ItemStack itemStack = itemStacks.get(i); ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack
IBlockState newBlockState = Blocks.AIR.getDefaultState();
if (itemStack.getItem() instanceof ItemBlock) {
newBlockState = newBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
}
if (player.world.isBlockLoaded(coordinate, true)) { if (player.world.isBlockLoaded(coordinate, true)) {
//check itemstack empty //check itemstack empty
if (itemStack.isEmpty()) { if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, newBlockStates.get(i)); itemStack = findItemStackInInventory(player, newBlockStates.get(i));
//get blockstate from new itemstack //get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) { if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) {
newBlockState = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); newBlockState = newBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} else {
newBlockState = Blocks.AIR.getDefaultState();
} }
} }
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true); if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true);
@@ -174,6 +208,8 @@ public class UndoRedo {
ItemStack itemStack = ItemStack.EMPTY; ItemStack itemStack = ItemStack.EMPTY;
//First try previousBlockStates //First try previousBlockStates
//TODO try to find itemstack with right blockstate first
// then change line 103 back (get state from item)
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
//then anything it drops //then anything it drops

View File

@@ -0,0 +1,94 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.util.ArrayList;
/***
* Sends a message to the client asking to add a block to the undo stack.
*/
public class AddUndoMessage implements IMessage {
private BlockPos coordinate;
private IBlockState previousBlockState;
private IBlockState newBlockState;
public AddUndoMessage() {
coordinate = BlockPos.ORIGIN;
previousBlockState = null;
newBlockState = null;
}
public AddUndoMessage(BlockPos coordinate, IBlockState previousBlockState, IBlockState newBlockState) {
this.coordinate = coordinate;
this.previousBlockState = previousBlockState;
this.newBlockState = newBlockState;
}
public BlockPos getCoordinate() {
return coordinate;
}
public IBlockState getPreviousBlockState() {
return previousBlockState;
}
public IBlockState getNewBlockState() {
return newBlockState;
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeInt(this.coordinate.getX());
buf.writeInt(this.coordinate.getY());
buf.writeInt(this.coordinate.getZ());
buf.writeInt(Block.getStateId(this.previousBlockState));
buf.writeInt(Block.getStateId(this.newBlockState));
}
@Override
public void fromBytes(ByteBuf buf) {
coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
previousBlockState = Block.getStateById(buf.readInt());
newBlockState = Block.getStateById(buf.readInt());
}
// The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<AddUndoMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(AddUndoMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side");
if (ctx.side == Side.CLIENT){
//Received clientside
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
UndoRedo.addUndo(player, new BlockSet(
new ArrayList<BlockPos>() {{add(message.getCoordinate());}},
new ArrayList<IBlockState>() {{add(message.getPreviousBlockState());}},
new ArrayList<IBlockState>() {{add(message.getNewBlockState());}},
new Vec3d(0,0,0),
message.getCoordinate(), message.getCoordinate()));
});
}
return null;
}
}
}

View File

@@ -0,0 +1,57 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.util.ArrayList;
/***
* Sends a message to the client asking to clear the undo and redo stacks.
*/
public class ClearUndoMessage implements IMessage {
public ClearUndoMessage() {
}
@Override
public void toBytes(ByteBuf buf) {
}
@Override
public void fromBytes(ByteBuf buf) {
}
// The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<ClearUndoMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(ClearUndoMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side");
if (ctx.side == Side.CLIENT){
//Received clientside
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
UndoRedo.clear(player);
});
}
return null;
}
}
}

View File

@@ -22,56 +22,27 @@ import java.util.ArrayList;
* This is then sent back with a BlockPlacedMessage. * This is then sent back with a BlockPlacedMessage.
*/ */
public class RequestLookAtMessage implements IMessage { public class RequestLookAtMessage implements IMessage {
private BlockPos coordinate;
private IBlockState previousBlockState;
private IBlockState newBlockState;
private boolean placeStartPos; private boolean placeStartPos;
public RequestLookAtMessage() { public RequestLookAtMessage() {
coordinate = BlockPos.ORIGIN;
previousBlockState = null;
newBlockState = null;
placeStartPos = false; placeStartPos = false;
} }
public RequestLookAtMessage(BlockPos coordinate, IBlockState previousBlockState, IBlockState newBlockState, boolean placeStartPos) { public RequestLookAtMessage(boolean placeStartPos) {
this.coordinate = coordinate;
this.previousBlockState = previousBlockState;
this.newBlockState = newBlockState;
this.placeStartPos = placeStartPos; this.placeStartPos = placeStartPos;
} }
public BlockPos getCoordinate() {
return coordinate;
}
public IBlockState getPreviousBlockState() {
return previousBlockState;
}
public IBlockState getNewBlockState() {
return newBlockState;
}
public boolean getPlaceStartPos() { public boolean getPlaceStartPos() {
return placeStartPos; return placeStartPos;
} }
@Override @Override
public void toBytes(ByteBuf buf) { public void toBytes(ByteBuf buf) {
buf.writeInt(this.coordinate.getX());
buf.writeInt(this.coordinate.getY());
buf.writeInt(this.coordinate.getZ());
buf.writeInt(Block.getStateId(this.previousBlockState));
buf.writeInt(Block.getStateId(this.newBlockState));
buf.writeBoolean(this.placeStartPos); buf.writeBoolean(this.placeStartPos);
} }
@Override @Override
public void fromBytes(ByteBuf buf) { public void fromBytes(ByteBuf buf) {
coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
previousBlockState = Block.getStateById(buf.readInt());
newBlockState = Block.getStateById(buf.readInt());
placeStartPos = buf.readBoolean(); placeStartPos = buf.readBoolean();
} }
@@ -87,17 +58,10 @@ public class RequestLookAtMessage implements IMessage {
//Received clientside //Received clientside
//Send back your info //Send back your info
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> { // EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); // EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//
//Add to undo stack clientside // });
UndoRedo.addUndo(player, new BlockSet(
new ArrayList<BlockPos>() {{add(message.getCoordinate());}},
new ArrayList<IBlockState>() {{add(message.getPreviousBlockState());}},
new ArrayList<IBlockState>() {{add(message.getNewBlockState());}},
new Vec3d(0,0,0),
message.getCoordinate(), message.getCoordinate()));
});
//Prevent double placing in normal mode with placeStartPos false. //Prevent double placing in normal mode with placeStartPos false.
//Unless QuickReplace is on, then we do need to place start pos. //Unless QuickReplace is on, then we do need to place start pos.