Added undo, redo functionality.

All placements use blocks from entire inventory now.
Added block count and dimensions in actionbar when placing/breaking blocks.
Added undo, redo, replace and 'open modifier settings' icons.
Fixed not being able to break blocks in creative when starting the selection on a tallgrass (instabreaking) block.
This commit is contained in:
Christian Knaapen
2019-03-15 20:46:47 +01:00
parent 2d45b1e574
commit 2cac2be29f
18 changed files with 399 additions and 59 deletions

View File

@@ -11,7 +11,7 @@ apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
version = "1.12.2-2.4" version = "1.12.2-2.5"
group = "nl.requios.effortlessbuilding" // http://maven.apache.org/guides/mini/guide-naming-conventions.html group = "nl.requios.effortlessbuilding" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "effortlessbuilding" archivesBaseName = "effortlessbuilding"

View File

@@ -52,6 +52,10 @@ public class BuildConfig {
"The block in front of you always counts as 100%."}) "The block in front of you always counts as 100%."})
@RangeInt(min = 0, max = 200) @RangeInt(min = 0, max = 200)
public int miningTimePercentage = 50; public int miningTimePercentage = 50;
@Comment({"How many placements are remembered for the undo functionality."})
@RequiresMcRestart
public int undoStackSize = 5;
} }
public static class Visuals { public static class Visuals {

View File

@@ -39,7 +39,7 @@ public class EffortlessBuilding
{ {
public static final String MODID = "effortlessbuilding"; public static final String MODID = "effortlessbuilding";
public static final String NAME = "Effortless Building"; public static final String NAME = "Effortless Building";
public static final String VERSION = "1.12.2-2.4"; public static final String VERSION = "1.12.2-2.5";
@Mod.Instance(EffortlessBuilding.MODID) @Mod.Instance(EffortlessBuilding.MODID)
public static EffortlessBuilding instance; public static EffortlessBuilding instance;

View File

@@ -119,8 +119,7 @@ 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) {
if (ReachHelper.canBreakFar(player) && if (ReachHelper.canBreakFar(player)) {
!CompatHelper.chiselsAndBitsProxy.isHoldingChiselTool(EnumHand.MAIN_HAND)) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null; BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null;
onBlockBroken(player, startPos, true); onBlockBroken(player, startPos, true);
@@ -132,7 +131,7 @@ public class BuildModes {
//Check if not in the middle of placing //Check if not in the middle of placing
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) { if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing //Cancel breaking
initializeMode(player); initializeMode(player);
return; return;
} }
@@ -177,4 +176,20 @@ public class BuildModes {
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player); ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
} }
public static boolean isCurrentlyPlacing(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && !currentlyBreaking.get(player);
}
public static boolean isCurrentlyBreaking(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && currentlyBreaking.get(player);
}
//Either placing or breaking
public static boolean isActive(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null;
}
} }

View File

@@ -7,6 +7,7 @@ import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu; import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui; import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
@@ -21,12 +22,15 @@ public class ModeOptions {
//Called on both client and server //Called on both client and server
public static void performAction(EntityPlayer player, ActionEnum action) { public static void performAction(EntityPlayer player, ActionEnum action) {
EffortlessBuilding.log("Doing "+action.name());
switch (action) { switch (action) {
case UNDO: case UNDO:
UndoRedo.undo(player);
EffortlessBuilding.log(player, "Undo", true);
break; break;
case REDO: case REDO:
UndoRedo.redo(player);
EffortlessBuilding.log(player, "Redo", true);
break; break;
case REPLACE: case REPLACE:
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);

View File

@@ -0,0 +1,45 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.List;
public class BlockSet {
private List<BlockPos> coordinates;
private List<IBlockState> blockStates;
private Vec3d hitVec;
private BlockPos firstPos;
private BlockPos secondPos;
public BlockSet(List<BlockPos> coordinates, List<IBlockState> blockStates, Vec3d hitVec,
BlockPos firstPos, BlockPos secondPos) {
this.coordinates = coordinates;
this.blockStates = blockStates;
this.hitVec = hitVec;
this.firstPos = firstPos;
this.secondPos = secondPos;
}
public List<BlockPos> getCoordinates() {
return coordinates;
}
public List<IBlockState> getBlockStates() {
return blockStates;
}
public Vec3d getHitVec() {
return hitVec;
}
public BlockPos getFirstPos() {
return firstPos;
}
public BlockPos getSecondPos() {
return secondPos;
}
}

View File

@@ -11,19 +11,21 @@ import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.FixedStack;
import nl.requios.effortlessbuilding.helper.InventoryHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
public class BuildModifiers { public class BuildModifiers {
//Called from BuildModes //Called from BuildModes
public static void onBlockPlaced(EntityPlayer player, List<BlockPos> startCoordinates, EnumFacing sideHit, Vec3d hitVec, boolean placeStartPos) { public static void onBlockPlaced(EntityPlayer player, List<BlockPos> startCoordinates, EnumFacing sideHit, Vec3d hitVec, boolean placeStartPos) {
World world = player.world; World world = player.world;
@@ -41,23 +43,33 @@ public class BuildModifiers {
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
if (world.isRemote) { if (world.isRemote) {
BlockPreviewRenderer.onBlocksPlaced(); BlockPreviewRenderer.onBlocksPlaced();
return;
}
//place blocks } else {
for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (world.isBlockLoaded(blockPos, true)) { //place blocks
//check itemstack empty for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
if (itemStack.isEmpty()) continue; BlockPos blockPos = coordinates.get(i);
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false); IBlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (world.isBlockLoaded(blockPos, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
//try to find new stack, otherwise continue
itemStack = InventoryHelper.findItemStackInInventory(player, blockState);
if (itemStack.isEmpty()) continue;
}
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false);
}
} }
} }
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new BlockSet(coordinates, blockStates, hitVec, firstPos, secondPos));
} }
public static void onBlockBroken(EntityPlayer player, List<BlockPos> posList, boolean breakStartPos) { public static void onBlockBroken(EntityPlayer player, List<BlockPos> posList, boolean breakStartPos) {
@@ -73,7 +85,8 @@ public class BuildModifiers {
} }
//If the player is going to instabreak grass or a plant, only break other instabreaking things //If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = world.getBlockState(posList.get(0)).getBlockHardness(world, posList.get(0)) == 0f; boolean onlyInstaBreaking = !player.isCreative() &&
world.getBlockState(posList.get(0)).getBlockHardness(world, posList.get(0)) == 0f;
//break all those blocks //break all those blocks
for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) { for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {

View File

@@ -0,0 +1,118 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.helper.FixedStack;
import nl.requios.effortlessbuilding.helper.InventoryHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.*;
public class UndoRedo {
private static Map<UUID, FixedStack<BlockSet>> undoStacks = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacks = new HashMap<>();
//add to undo stack
public static void addUndo(EntityPlayer player, BlockSet blockSet) {
//If no stack exists, make one
if (!undoStacks.containsKey(player.getUniqueID())) {
undoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize]));
}
undoStacks.get(player.getUniqueID()).push(blockSet);
}
private static void addRedo(EntityPlayer player, BlockSet blockSet) {
//If no stack exists, make one
if (!redoStacks.containsKey(player.getUniqueID())) {
redoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize]));
}
redoStacks.get(player.getUniqueID()).push(blockSet);
}
public static boolean undo(EntityPlayer player) {
if (!undoStacks.containsKey(player.getUniqueID())) return false;
FixedStack<BlockSet> undoStack = undoStacks.get(player.getUniqueID());
if (undoStack.isEmpty()) return false;
BlockSet blockSet = undoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> blockStates = blockSet.getBlockStates();
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, blockStates);
//break all those blocks
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (player.world.isBlockLoaded(coordinate, false)) {
SurvivalHelper.breakBlock(player.world, player, coordinate);
}
}
if (player.world.isRemote)
BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, blockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
//add to redo
addRedo(player, blockSet);
return true;
}
public static boolean redo(EntityPlayer player) {
if (!redoStacks.containsKey(player.getUniqueID())) return false;
FixedStack<BlockSet> redoStack = redoStacks.get(player.getUniqueID());
if (redoStack.isEmpty()) return false;
BlockSet blockSet = redoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> blockStates = blockSet.getBlockStates();
Vec3d hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, blockStates);
//place blocks
for (int i = 0; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (player.world.isBlockLoaded(blockPos, true)) {
//check itemstack empty
if (itemStack.isEmpty()) continue;
SurvivalHelper.placeBlock(player.world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false);
}
}
if (player.world.isRemote)
BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, blockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
//add to undo
addUndo(player, blockSet);
return true;
}
private static List<ItemStack> findItemStacksInInventory(EntityPlayer player, List<IBlockState> blockStates) {
List<ItemStack> itemStacks = new ArrayList<>(blockStates.size());
for (IBlockState blockState : blockStates) {
itemStacks.add(InventoryHelper.findItemStackInInventory(player, blockState));
}
return itemStacks;
}
}

View File

@@ -265,12 +265,10 @@ public class RadialMenu extends GuiScreen {
final TextureAtlasSprite sprite = ClientProxy.getBuildModeIcon(menuRegion.mode); final TextureAtlasSprite sprite = ClientProxy.getBuildModeIcon(menuRegion.mode);
final double scalex = 16 * 0.5; final double x1 = x - 8;
final double scaley = 16 * 0.5; final double x2 = x + 8;
final double x1 = x - scalex; final double y1 = y - 8;
final double x2 = x + scalex; final double y2 = y + 8;
final double y1 = y - scaley;
final double y2 = y + scaley;
final float f = 1f; final float f = 1f;
final float a = 1f; final float a = 1f;
@@ -298,8 +296,8 @@ public class RadialMenu extends GuiScreen {
final TextureAtlasSprite sprite = ClientProxy.getModeOptionIcon(button.action); final TextureAtlasSprite sprite = ClientProxy.getModeOptionIcon(button.action);
final double btnmiddleX = (button.x1 + button.x2) / 2.0; final double btnmiddleX = (button.x1 + button.x2) / 2 + 0.01;
final double btnmiddleY = (button.y1 + button.y2) / 2.0; final double btnmiddleY = (button.y1 + button.y2) / 2 + 0.01;
final double btnx1 = btnmiddleX - 8; final double btnx1 = btnmiddleX - 8;
final double btnx2 = btnmiddleX + 8; final double btnx2 = btnmiddleX + 8;
final double btny1 = btnmiddleY - 8; final double btny1 = btnmiddleY - 8;
@@ -337,15 +335,23 @@ public class RadialMenu extends GuiScreen {
if (button.highlighted) { if (button.highlighted) {
String text = TextFormatting.AQUA + button.name; String text = TextFormatting.AQUA + button.name;
int wrap = 120; int wrap = 120;
String keybind = TextFormatting.GRAY + "(None)"; String keybind = "None";
//Add keybind in brackets //Add keybind in brackets
if (button.action == ModeOptions.ActionEnum.UNDO) {
keybind = ClientProxy.keyBindings[4].getDisplayName();
}
if (button.action == ModeOptions.ActionEnum.REDO) {
String sneak = Minecraft.getMinecraft().gameSettings.keyBindSneak.getDisplayName();
keybind = sneak + " + " + ClientProxy.keyBindings[4].getDisplayName();
}
if (button.action == ModeOptions.ActionEnum.REPLACE) { if (button.action == ModeOptions.ActionEnum.REPLACE) {
keybind = TextFormatting.GRAY + " (" + WordUtils.capitalizeFully(ClientProxy.keyBindings[1].getDisplayName().toLowerCase()) + ")"; keybind = ClientProxy.keyBindings[1].getDisplayName();
} }
if (button.action == ModeOptions.ActionEnum.OPEN_MODIFIER_SETTINGS) { if (button.action == ModeOptions.ActionEnum.OPEN_MODIFIER_SETTINGS) {
keybind = TextFormatting.GRAY + " (" + WordUtils.capitalizeFully(ClientProxy.keyBindings[0].getDisplayName()) + ")"; keybind = ClientProxy.keyBindings[0].getDisplayName();
} }
String keybindFormatted = TextFormatting.GRAY + " (" + WordUtils.capitalizeFully(keybind) + ")";
if (button.textSide == EnumFacing.WEST) { if (button.textSide == EnumFacing.WEST) {
@@ -362,7 +368,7 @@ public class RadialMenu extends GuiScreen {
fontRenderer.drawSplitString( text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5), fontRenderer.drawSplitString( text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5),
(int) (middleY + button.y1 - 26), wrap,0xffffffff); (int) (middleY + button.y1 - 26), wrap,0xffffffff);
fontRenderer.drawSplitString( keybind, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybind) * 0.5), fontRenderer.drawSplitString( keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybindFormatted) * 0.5),
(int) (middleY + button.y1 - 14), wrap,0xffffffff); (int) (middleY + button.y1 - 14), wrap,0xffffffff);
} else if (button.textSide == EnumFacing.DOWN || button.textSide == EnumFacing.SOUTH) { } else if (button.textSide == EnumFacing.DOWN || button.textSide == EnumFacing.SOUTH) {
@@ -370,7 +376,7 @@ public class RadialMenu extends GuiScreen {
fontRenderer.drawSplitString(text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5), fontRenderer.drawSplitString(text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5),
(int) (middleY + button.y1 + 24), wrap, 0xffffffff); (int) (middleY + button.y1 + 24), wrap, 0xffffffff);
fontRenderer.drawSplitString(keybind, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybind) * 0.5), fontRenderer.drawSplitString(keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybindFormatted) * 0.5),
(int) (middleY + button.y1 + 36), wrap, 0xffffffff); (int) (middleY + button.y1 + 36), wrap, 0xffffffff);
} }

View File

@@ -0,0 +1,52 @@
package nl.requios.effortlessbuilding.helper;
//Stack with fixed size. Removes (overwrites) oldest element on push.
public class FixedStack<T> {
private T[] stack;
private int size;
private int top;
private int filled = 0; //how many valid items are in the stack
public FixedStack(T[] stack) {
this.stack = stack;
this.top = 0;
this.size = stack.length;
}
public void push(T object) {
if (top == stack.length)
top = 0;
stack[top] = object;
top++;
if (filled < size - 1)
filled++;
}
public T pop() {
if (filled <= 0) return null;
if (top - 1 < 0)
top = size;
top--;
T object = stack[top];
filled--;
return object;
}
public void clear() {
top = 0;
filled = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return filled <= 0;
}
}

View File

@@ -0,0 +1,30 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
public class InventoryHelper {
public static ItemStack findItemStackInInventory(EntityPlayer player, IBlockState blockState) {
for (ItemStack invStack : player.inventory.mainInventory) {
if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock &&
((ItemBlock) invStack.getItem()).getBlock().equals(blockState.getBlock())) {
return invStack;
}
}
return ItemStack.EMPTY;
}
public static int findTotalBlocksInInventory(EntityPlayer player, IBlockState blockState) {
int total = 0;
for (ItemStack invStack : player.inventory.mainInventory) {
if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock &&
((ItemBlock) invStack.getItem()).getBlock().equals(blockState.getBlock())) {
total += invStack.getCount();
}
}
return total;
}
}

View File

@@ -77,14 +77,15 @@ public class ClientProxy implements IProxy {
@Override @Override
public void init(FMLInitializationEvent event) { public void init(FMLInitializationEvent event) {
// register key bindings // register key bindings
keyBindings = new KeyBinding[4]; keyBindings = new KeyBinding[5];
// instantiate the key bindings // instantiate the key bindings
keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category"); keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category"); keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_NONE, "key.effortlessbuilding.category"); keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_NONE, "key.effortlessbuilding.category");
keyBindings[3] = new KeyBinding("key.effortlessbuilding.mode.desc", Keyboard.KEY_LMENU, "key.effortlessbuilding.category"); keyBindings[3] = new KeyBinding("key.effortlessbuilding.mode.desc", Keyboard.KEY_LMENU, "key.effortlessbuilding.category");
// keyBindings[4] = new KeyBinding("Reload shaders", Keyboard.KEY_TAB, "key.effortlessbuilding.category"); keyBindings[4] = new KeyBinding("key.effortlessbuilding.undo.desc", Keyboard.KEY_U, "key.effortlessbuilding.category");
// keyBindings[5] = new KeyBinding("Reload shaders", Keyboard.KEY_TAB, "key.effortlessbuilding.category");
// register all the key bindings // register all the key bindings
for (int i = 0; i < keyBindings.length; ++i) { for (int i = 0; i < keyBindings.length; ++i) {
@@ -318,8 +319,16 @@ public class ClientProxy implements IProxy {
} }
} }
// if (keyBindings[4].isPressed()) { //Undo
// //TODO remove if (keyBindings[4].isPressed()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.UNDO;
if (player.isSneaking()) action = ModeOptions.ActionEnum.REDO;
ModeOptions.performAction(player, action);
EffortlessBuilding.packetHandler.sendToServer(new ModeActionMessage(action));
}
//For shader development
// if (keyBindings[5].isPressed()) {
// ShaderHandler.init(); // ShaderHandler.init();
// EffortlessBuilding.log(player, "Reloaded shaders"); // EffortlessBuilding.log(player, "Reloaded shaders");
// } // }

View File

@@ -26,6 +26,7 @@ import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.InventoryHelper;
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.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
@@ -158,12 +159,7 @@ public class BlockPreviewRenderer {
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
Collections.sort(newCoordinates, (lhs, rhs) -> { sortOnDistanceToPlayer(newCoordinates, player);
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getPositionEyes(1f)).lengthSquared();
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getPositionEyes(1f)).lengthSquared();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z))); Math.abs(hitVec.z - ((int) hitVec.z)));
@@ -206,12 +202,14 @@ public class BlockPreviewRenderer {
//Render block previews //Render block previews
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
int blockCount;
//Use fancy shader if config allows, otherwise outlines //Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders && newCoordinates.size() < BuildConfig.visuals.shaderTreshold) { if (BuildConfig.visuals.useShaders && newCoordinates.size() < BuildConfig.visuals.shaderTreshold) {
RenderHandler.beginBlockPreviews(); RenderHandler.beginBlockPreviews();
renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking); blockCount = renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
RenderHandler.endBlockPreviews(); RenderHandler.endBlockPreviews();
} else { } else {
@@ -227,8 +225,27 @@ public class BlockPreviewRenderer {
} }
RenderHandler.endLines(); RenderHandler.endLines();
blockCount = newCoordinates.size();
}
//Display block count and dimensions in actionbar
if (BuildModes.isActive(player)) {
BlockPos dim = secondPos.subtract(firstPos);
dim = new BlockPos(Math.abs(dim.getX()) + 1, Math.abs(dim.getY()) + 1, Math.abs(dim.getZ()) + 1);
String dimensions = "(";
if (dim.getX() > 1) dimensions += dim.getX() + "x";
if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
if (dim.getY() > 1) dimensions += dim.getY() + "x";
dimensions = dimensions.substring(0, dimensions.length() - 1);
if (dimensions.length() > 1) dimensions += ")";
EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
} }
} }
} }
RenderHandler.beginLines(); RenderHandler.beginLines();
@@ -264,14 +281,15 @@ public class BlockPreviewRenderer {
BuildConfig.visuals.alwaysShowBlockPreview; BuildConfig.visuals.alwaysShowBlockPreview;
} }
protected static void renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates, protected static int renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos, List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace, boolean red) { BlockPos secondPos, boolean checkCanPlace, boolean red) {
EntityPlayer player = Minecraft.getMinecraft().player; EntityPlayer player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
int blocksValid = 0;
if (coordinates.isEmpty()) return; if (coordinates.isEmpty()) return blocksValid;
for (int i = coordinates.size() - 1; i >= 0; i--) { for (int i = coordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = coordinates.get(i); BlockPos blockPos = coordinates.get(i);
@@ -289,43 +307,57 @@ public class BlockPreviewRenderer {
new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos), new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos),
blockPos == secondPos, red)); blockPos == secondPos, red));
RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState); RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState);
blocksValid++;
} }
} }
return blocksValid;
} }
public static void onBlocksPlaced() { public static void onBlocksPlaced() {
onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<IBlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
EntityPlayerSP player = Minecraft.getMinecraft().player; EntityPlayerSP player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled //Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) { if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks //Save current coordinates, blockstates and itemstacks
if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() && if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
previousCoordinates.size() > 1 && previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) { coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
previousItemStacks, previousFirstPos, previousSecondPos, false)); itemStacks, firstPos, secondPos, false));
} }
} }
} }
public static void onBlocksBroken() { public static void onBlocksBroken() {
onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<IBlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
EntityPlayerSP player = Minecraft.getMinecraft().player; EntityPlayerSP player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled //Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) { if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks //Save current coordinates, blockstates and itemstacks
if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() && if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
previousCoordinates.size() > 1 && previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) { coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, sortOnDistanceToPlayer(coordinates, player);
previousItemStacks, previousFirstPos, previousSecondPos, true));
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, true));
} }
} }
@@ -373,4 +405,15 @@ public class BlockPreviewRenderer {
ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0); ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0);
}; };
} }
private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, EntityPlayer player) {
Collections.sort(coordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getPositionEyes(1f)).lengthSquared();
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getPositionEyes(1f)).lengthSquared();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
}
} }

View File

@@ -3,6 +3,7 @@ key.effortlessbuilding.hud.desc=Modifier Menu
key.effortlessbuilding.replace.desc=Toggle QuickReplace key.effortlessbuilding.replace.desc=Toggle QuickReplace
key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode
key.effortlessbuilding.mode.desc=Radial Menu key.effortlessbuilding.mode.desc=Radial Menu
key.effortlessbuilding.undo.desc=Undo
item.effortlessbuilding:randomizer_bag.name=Randomizer Bag item.effortlessbuilding:randomizer_bag.name=Randomizer Bag
item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1 item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1
@@ -19,8 +20,8 @@ effortlessbuilding.mode.diagonal_wall=Diagonal Wall (WIP)
effortlessbuilding.mode.slope_floor=Slope Floor (WIP) effortlessbuilding.mode.slope_floor=Slope Floor (WIP)
effortlessbuilding.mode.cube=Cube (WIP) effortlessbuilding.mode.cube=Cube (WIP)
effortlessbuilding.action.undo=Undo (WIP) effortlessbuilding.action.undo=Undo
effortlessbuilding.action.redo=Redo (WIP) effortlessbuilding.action.redo=Redo
effortlessbuilding.action.replace=Replace effortlessbuilding.action.replace=Replace
effortlessbuilding.action.open_modifier_settings=Open Modifier Settings effortlessbuilding.action.open_modifier_settings=Open Modifier Settings

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 1.2 KiB