5 Commits
0.4 ... 0.5

Author SHA1 Message Date
Christian Knaapen
13d43a0265 Added breaking animation to all breakable blocks.
Smart preview: only blocks that can be (re)placed show a preview.
Smart outline when breaking: only blocks that can be broken by the current tool get an outline.
Improved occlusion by render further block previews first.
Reversed order of mirror and array to mirror arrays (for roofs etc).
2018-12-15 16:59:13 +01:00
Christian Knaapen
408d96622b Implemented new block preview for mirror and array, quickreplace and randomizer bag.
Refactored buildmodifiers to use findCoordinates and findBlockStates.
2018-12-14 20:12:18 +01:00
Christian Knaapen
2a487f2864 Testing a new block preview 2018-12-14 00:21:04 +01:00
Christian Knaapen
d745a868e5 Settings entries can be collapsed (GuiList with custom height).
Entries are centered vertically if it fits.
2018-12-04 20:00:04 +01:00
Christian Knaapen
ee4ac6f098 Made settings GUI scrollable for future use.
Split mirror and array settings GUI into their own classes (scrollEntries).
2018-12-02 18:31:25 +01:00
22 changed files with 1746 additions and 885 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 = "0.3.5" version = "0.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

@@ -7,6 +7,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; 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.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
@@ -15,6 +16,9 @@ import net.minecraftforge.items.IItemHandler;
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 java.util.ArrayList;
import java.util.List;
public class Array { public class Array {
public static class ArraySettings{ public static class ArraySettings{
@@ -42,21 +46,33 @@ public class Array {
} }
} }
//Called from EventHandler public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
public static boolean onBlockPlaced(BlockEvent.PlaceEvent event) { List<BlockPos> coordinates = new ArrayList<>();
if (event.getWorld().isRemote) return false;
//find arraysettings for the player that placed the block //find arraysettings for the player
ArraySettings a = BuildSettingsManager.getBuildSettings(event.getPlayer()).getArraySettings(); ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (a == null || !a.enabled) return false; if (!isEnabled(a)) return coordinates;
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return false; BlockPos pos = startPos;
BlockPos pos = event.getPos();
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ()); Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
//Get itemstack for (int i = 0; i < a.count; i++) {
ItemStack itemStack = event.getPlayer().getHeldItem(event.getHand()); pos = pos.add(offset);
coordinates.add(pos);
}
return coordinates;
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, IBlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
//find arraysettings for the player that placed the block
ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (!isEnabled(a)) return blockStates;
BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
//Randomizer bag synergy //Randomizer bag synergy
IItemHandler bagInventory = null; IItemHandler bagInventory = null;
@@ -66,68 +82,27 @@ public class Array {
for (int i = 0; i < a.count; i++) { for (int i = 0; i < a.count; i++) {
pos = pos.add(offset); pos = pos.add(offset);
if (event.getWorld().isBlockLoaded(pos, true)) {
if (itemStack.isEmpty()) break;
IBlockState blockState = event.getPlacedBlock();
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
if (itemStack.isEmpty()) continue; blockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
blockState = getBlockStateFromRandomizerBag(bagInventory, event.getWorld(), event.getPlayer(), event.getPos(), itemStack, event.getHand());
if (blockState == null) continue;
} }
//TODO check if can place (ItemBlock) and if can break replaced //blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
blockStates.add(blockState);
itemStacks.add(itemStack);
}
SurvivalHelper.placeBlock(event.getWorld(), event.getPlayer(), pos, blockState, itemStack, EnumFacing.NORTH, true, false); return blockStates;
}
} }
public static boolean isEnabled(ArraySettings a) {
if (a == null || !a.enabled) return false;
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return false;
return true; return true;
} }
private static IBlockState getBlockStateFromRandomizerBag(IItemHandler bagInventory, World world, EntityPlayer player, BlockPos pos, ItemStack itemStack, EnumHand hand) {
//TODO get facing from getPlacedAgainst and getPlacedBlock
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(world, pos, EnumFacing.NORTH, 0, 0, 0, itemStack.getMetadata(), player, hand);
}
//Called from EventHandler
public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote) return;
//find arraysettings for the player that broke the block
ArraySettings a = BuildSettingsManager.getBuildSettings(event.getPlayer()).getArraySettings();
if (a == null || !a.enabled) return;
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return;
BlockPos pos = event.getPos();
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
for (int i = 0; i < a.count; i++) {
pos = pos.add(offset);
SurvivalHelper.breakBlock(event.getWorld(), event.getPlayer(), pos);
}
}
//Called from EventHandler
public static float getTotalBlockHardness(World world, EntityPlayer player, BlockPos pos) {
float hardness = 0;
//find arraysettings for the player that broke the block
ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (a == null || !a.enabled) return 0;
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return 0;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
for (int i = 0; i < a.count; i++) {
pos = pos.add(offset);
if (SurvivalHelper.canBreak(world, player, pos))
hardness += world.getBlockState(pos).getBlockHardness(world, pos);
}
return hardness;
}
} }

View File

@@ -19,13 +19,13 @@ public class BuildConfig {
@Comment({"Maximum reach in survival without upgrades", @Comment({"Maximum reach in survival without upgrades",
"Reach upgrades are craftable consumables that permanently increase reach.", "Reach upgrades are craftable consumables that permanently increase reach.",
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade."}) "Set to 0 to disable Effortless Building until the player has consumed a reach upgrade."})
public int maxReachLevel0 = 10; public int maxReachLevel0 = 20;
@Comment("Maximum reach in survival with one upgrade") @Comment("Maximum reach in survival with one upgrade")
public int maxReachLevel1 = 20; public int maxReachLevel1 = 50;
@Comment("Maximum reach in survival with two upgrades") @Comment("Maximum reach in survival with two upgrades")
public int maxReachLevel2 = 50; public int maxReachLevel2 = 100;
@Comment("Maximum reach in survival with three upgrades") @Comment("Maximum reach in survival with three upgrades")
public int maxReachLevel3 = 200; public int maxReachLevel3 = 200;
@@ -47,8 +47,8 @@ public class BuildConfig {
} }
public static class Visuals { public static class Visuals {
@Comment({"Shows a white block outline for the block you manually place,", @Comment({"Show a block preview if you have a block in hand,",
"in addition to blocks placed by the mirror or array."}) "even when mirror and array are off."})
public boolean showOutlineOnCurrentBlock = false; public boolean alwaysShowBlockPreview = false;
} }
} }

View File

@@ -0,0 +1,185 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import java.util.*;
public class BuildModifiers {
//Uses a network message to get the previous raytraceresult from the player
//The server could keep track of all raytraceresults but this might lag with many players
//Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) {
if (!message.isBlockHit() || message.getBlockPos() == null) return;
World world = player.world;
ItemRandomizerBag.renewRandomness();
BlockPos startPos = message.getBlockPos();
//Offset in direction of sidehit if not quickreplace and not replaceable
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
boolean replaceable = world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!buildSettings.doQuickReplace() && !replaceable) {
startPos = startPos.offset(message.getSideHit());
}
//Get under tall grass and other replaceable blocks
if (buildSettings.doQuickReplace() && replaceable) {
startPos = startPos.down();
}
//Format hitvec to 0.x
Vec3d hitVec = message.getHitVec();
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z)));
//find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, startPos);
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = findBlockStates(player, startPos, hitVec, message.getSideHit(), itemStacks);
//check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
//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 (world.isBlockLoaded(blockPos, true)) {
//check itemstack empty
if (itemStack.isEmpty()) continue;
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, true, false);
}
}
}
public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
if (event.getWorld().isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own place event if anything is enabled
if (isEnabled(buildSettings, event.getPos())) {
EffortlessBuilding.packetHandler.sendTo(new BlockPlacedMessage(), (EntityPlayerMP) event.getPlayer());
event.setCanceled(true);
}
}
public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own break event if anything is enabled
if (isEnabled(buildSettings, event.getPos())) {
//get coordinates
List<BlockPos> coordinates = findCoordinates(event.getPlayer(), event.getPos());
//break all those blocks
for (BlockPos coordinate : coordinates) {
if (event.getWorld().isBlockLoaded(coordinate, false)) {
SurvivalHelper.breakBlock(event.getWorld(), event.getPlayer(), coordinate);
}
}
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current block being placed too
coordinates.add(startPos);
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, startPos));
//get array for each coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
}
return coordinates;
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, Vec3d hitVec, EnumFacing facing, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
itemStacks.clear();
//Get itemstack
ItemStack itemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (itemStack.isEmpty() || !(itemStack.getItem() instanceof ItemBlock || itemStack.getItem() instanceof ItemRandomizerBag)) {
itemStack = player.getHeldItem(EnumHand.OFF_HAND);
}
if (itemStack.isEmpty() || !(itemStack.getItem() instanceof ItemBlock || itemStack.getItem() instanceof ItemRandomizerBag)) {
return blockStates;
}
//Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack;
ItemRandomizerBag.resetRandomness();
if (itemStack.getItem() instanceof ItemRandomizerBag) itemBlock = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack));
IBlockState blockState = getBlockStateFromItem(itemBlock, player, startPos, facing, hitVec, EnumHand.MAIN_HAND);
//Add current block being placed too
blockStates.add(blockState);
itemStacks.add(itemStack);
List<IBlockState> arrayBlockStates = Array.findBlockStates(player, startPos, blockState, itemStack, itemStacks);
blockStates.addAll(arrayBlockStates);
blockStates.addAll(Mirror.findBlockStates(player, startPos, blockState, itemStack, itemStacks));
//add array for each mirror coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
IBlockState blockState1 = arrayBlockStates.get(i);
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
// List<BlockPos> coordinates = findCoordinates(player, startPos);
// for (int i = 0; i < blockStates.size(); i++) {
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
// }
return blockStates;
}
public static boolean isEnabled(BuildSettingsManager.BuildSettings buildSettings, BlockPos startPos) {
return Mirror.isEnabled(buildSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(buildSettings.getArraySettings()) ||
buildSettings.doQuickReplace();
}
public static IBlockState getBlockStateFromItem(ItemStack itemStack, EntityPlayer player, BlockPos blockPos, EnumFacing facing, Vec3d hitVec, EnumHand hand) {
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(player.world, blockPos, facing,
((float) hitVec.x), ((float) hitVec.y), ((float) hitVec.z), itemStack.getMetadata(), player, hand);
}
//Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false;
return coordinates1.equals(coordinates2);
}
}

View File

@@ -2,27 +2,27 @@ package nl.requios.effortlessbuilding;
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.util.text.TextFormatting;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import nl.requios.effortlessbuilding.capability.BuildModifierCapability; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class BuildSettingsManager { public class BuildSettingsManager {
//Retrieves the buildsettings of a player through the buildModifier capability //Retrieves the buildsettings of a player through the buildModifierCapability capability
//Never returns null //Never returns null
public static BuildSettings getBuildSettings(EntityPlayer player){ public static BuildSettings getBuildSettings(EntityPlayer player){
if (player.hasCapability(BuildModifierCapability.buildModifier, null)) { if (player.hasCapability(BuildModifierCapabilityManager.buildModifierCapability, null)) {
BuildModifierCapability.IBuildModifier capability = player.getCapability(BuildModifierCapability.buildModifier, null); BuildModifierCapabilityManager.IBuildModifierCapability capability = player.getCapability(
BuildModifierCapabilityManager.buildModifierCapability, null);
if (capability.getBuildModifierData() == null) { if (capability.getBuildModifierData() == null) {
capability.setBuildModifierData(new BuildSettings()); capability.setBuildModifierData(new BuildSettings());
} }
return capability.getBuildModifierData(); return capability.getBuildModifierData();
} }
throw new IllegalArgumentException("Player does not have buildModifier capability"); throw new IllegalArgumentException("Player does not have buildModifierCapability capability");
} }
public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) { public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) {
@@ -30,8 +30,9 @@ public class BuildSettingsManager {
EffortlessBuilding.log("Cannot set buildsettings, player is null"); EffortlessBuilding.log("Cannot set buildsettings, player is null");
return; return;
} }
if (player.hasCapability(BuildModifierCapability.buildModifier, null)) { if (player.hasCapability(BuildModifierCapabilityManager.buildModifierCapability, null)) {
BuildModifierCapability.IBuildModifier capability = player.getCapability(BuildModifierCapability.buildModifier, null); BuildModifierCapabilityManager.IBuildModifierCapability capability = player.getCapability(
BuildModifierCapabilityManager.buildModifierCapability, null);
capability.setBuildModifierData(buildSettings); capability.setBuildModifierData(buildSettings);
} else { } else {
EffortlessBuilding.log(player, "Saving buildsettings failed."); EffortlessBuilding.log(player, "Saving buildsettings failed.");
@@ -46,23 +47,23 @@ public class BuildSettingsManager {
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m.radius < 1) { if (m.radius < 1) {
m.radius = 1; m.radius = 1;
error += "Mirror size is too small. Size has been reset to 1. "; error += "Mirror size is too small. Size has been set to 1. ";
} }
if (m.getReach() > maxReach) { if (m.getReach() > maxReach) {
m.radius = maxReach / 2; m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach. Reach has been reset to max. "; error += "Mirror exceeds your maximum reach. Reach has been set to max. ";
} }
//Array settings //Array settings
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = buildSettings.getArraySettings();
if (a.count < 0) { if (a.count < 0) {
a.count = 0; a.count = 0;
error += "Array count cannot be negative. Count has been reset to 0. "; error += "Array count cannot be negative. Count has been set to 0. ";
} }
if (a.getReach() > maxReach) { if (a.getReach() > maxReach) {
a.count = 0; a.count = 0;
error += "Array exceeds your maximum reach. Count has been reset to 0. "; error += "Array exceeds your maximum reach. Count has been set to 0. ";
} }
//Other //Other

View File

@@ -21,7 +21,7 @@ import nl.requios.effortlessbuilding.capability.*;
import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler; import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.network.QuickReplaceMessage; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.proxy.IProxy; import nl.requios.effortlessbuilding.proxy.IProxy;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -31,7 +31,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 = "0.3.5"; public static final String VERSION = "0.5";
@Mod.Instance(EffortlessBuilding.MODID) @Mod.Instance(EffortlessBuilding.MODID)
public static EffortlessBuilding instance; public static EffortlessBuilding instance;
@@ -63,13 +63,14 @@ public class EffortlessBuilding
{ {
logger = event.getModLog(); logger = event.getModLog();
CapabilityManager.INSTANCE.register(BuildModifierCapability.IBuildModifier.class, new BuildModifierCapability.Storage(), BuildModifierCapability.BuildModifier.class); CapabilityManager.INSTANCE.register(
BuildModifierCapabilityManager.IBuildModifierCapability.class, new BuildModifierCapabilityManager.Storage(), BuildModifierCapabilityManager.BuildModifierCapability.class);
EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.CLIENT); EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(QuickReplaceMessage.MessageHandler.class, QuickReplaceMessage.class, 1, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 1, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(QuickReplaceMessage.MessageHandler.class, QuickReplaceMessage.class, 1, Side.CLIENT); EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 1, Side.CLIENT);
proxy.preInit(event); proxy.preInit(event);
} }

View File

@@ -7,31 +7,30 @@ import net.minecraft.entity.player.EntityPlayer;
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;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.config.Config; import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager; import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent; import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent;
import nl.requios.effortlessbuilding.capability.BuildModifierCapability; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import java.util.ArrayList;
import java.util.List;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class EventHandler public class EventHandler
{ {
private static boolean placedBlock = false;
private static BlockEvent.PlaceEvent placeEvent = null;
@SubscribeEvent @SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) public static void registerBlocks(RegistryEvent.Register<Block> event)
@@ -53,7 +52,7 @@ public class EventHandler
@SubscribeEvent @SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) { public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof EntityPlayer) { if (event.getObject() instanceof EntityPlayer) {
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "BuildModifier"), new BuildModifierCapability.Provider()); event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "BuildModifier"), new BuildModifierCapabilityManager.Provider());
} }
} }
@@ -66,33 +65,19 @@ public class EventHandler
} }
} }
@SubscribeEvent // @SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent event) { // public static void onServerTick(TickEvent.ServerTickEvent event) {
if (placedBlock) { //
placedBlock = false; // }
Mirror.onBlockPlaced(placeEvent);
Array.onBlockPlaced(placeEvent);
}
}
@SubscribeEvent @SubscribeEvent
public static void onBlockPlaced(BlockEvent.PlaceEvent event) { public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
if (QuickReplace.onBlockPlaced(event)) { BuildModifiers.onBlockPlaced(event);
event.setCanceled(true);
return;
}
//Delay mirror and array by a tick so we can edit the held itemstack
//Otherwise the itemstack count would be overridden by ItemBlock#onItemUse
placedBlock = true;
placeEvent = event;
} }
@SubscribeEvent @SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) { public static void onBlockBroken(BlockEvent.BreakEvent event) {
Mirror.onBlockBroken(event); BuildModifiers.onBlockBroken(event);
Array.onBlockBroken(event);
} }
@SubscribeEvent @SubscribeEvent
@@ -108,8 +93,16 @@ public class EventHandler
float originalBlockHardness = event.getState().getBlockHardness(world, pos); float originalBlockHardness = event.getState().getBlockHardness(world, pos);
float totalBlockHardness = 0; float totalBlockHardness = 0;
totalBlockHardness += Mirror.getTotalBlockHardness(world, player, pos); //get coordinates
totalBlockHardness += Array.getTotalBlockHardness(world, player, pos); List<BlockPos> coordinates = BuildModifiers.findCoordinates(player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
//get existing blockstates at those coordinates
IBlockState blockState = world.getBlockState(coordinate);
//add hardness for each blockstate, if can break
if (SurvivalHelper.canBreak(world, player, coordinate))
totalBlockHardness += blockState.getBlockHardness(world, coordinate);
}
//Grabbing percentage from config //Grabbing percentage from config
float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage / 100; float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage / 100;

View File

@@ -16,6 +16,9 @@ import net.minecraftforge.items.IItemHandler;
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 java.util.ArrayList;
import java.util.List;
public class Mirror { public class Mirror {
public static class MirrorSettings { public static class MirrorSettings {
@@ -23,7 +26,7 @@ public class Mirror {
public Vec3d position = new Vec3d(0.5, 64.5, 0.5); public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public boolean mirrorX = true, mirrorY = false, mirrorZ = false; public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
public int radius = 20; public int radius = 20;
public boolean drawLines = true, drawPlanes = false; public boolean drawLines = true, drawPlanes = true;
public MirrorSettings() { public MirrorSettings() {
} }
@@ -44,26 +47,52 @@ public class Mirror {
} }
} }
//Called from EventHandler public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
public static boolean onBlockPlaced(BlockEvent.PlaceEvent event) { List<BlockPos> coordinates = new ArrayList<>();
if (event.getWorld().isRemote) return false;
//find mirrorsettings for the player that placed the block //find mirrorsettings for the player
MirrorSettings m = BuildSettingsManager.getBuildSettings(event.getPlayer()).getMirrorSettings(); MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings();
if (m == null) return false; if (!isEnabled(m, startPos)) return coordinates;
if (!m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false; if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates);
//if within mirror distance, mirror return coordinates;
BlockPos oldBlockPos = event.getPos(); }
if (oldBlockPos.getX() + 0.5 < m.position.x - m.radius || oldBlockPos.getX() + 0.5 > m.position.x + m.radius || private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
oldBlockPos.getY() + 0.5 < m.position.y - m.radius || oldBlockPos.getY() + 0.5 > m.position.y + m.radius || //find mirror position
oldBlockPos.getZ() + 0.5 < m.position.z - m.radius || oldBlockPos.getZ() + 0.5 > m.position.z + m.radius) double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
return false; BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
coordinates.add(newBlockPos);
//Get itemstack if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates);
ItemStack itemStack = event.getPlayer().getHeldItem(event.getHand()); if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
}
private static void coordinateMirrorY(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
}
private static void coordinateMirrorZ(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
coordinates.add(newBlockPos);
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, IBlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
//find mirrorsettings for the player
MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates;
//Randomizer bag synergy //Randomizer bag synergy
IItemHandler bagInventory = null; IItemHandler bagInventory = null;
@@ -71,23 +100,15 @@ public class Mirror {
bagInventory = ItemRandomizerBag.getBagInventory(itemStack); bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
} }
if (m.mirrorX) { if (m.mirrorX) blockStateMirrorX(player, m, startPos, blockState, bagInventory, itemStack, EnumHand.MAIN_HAND, blockStates, itemStacks);
placeMirrorX(event.getWorld(), event.getPlayer(), m, event.getPos(), event.getPlacedBlock(), bagInventory, itemStack, event.getHand()); if (m.mirrorY) blockStateMirrorY(player, m, startPos, blockState, bagInventory, itemStack, EnumHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorZ) blockStateMirrorZ(player, m, startPos, blockState, bagInventory, itemStack, EnumHand.MAIN_HAND, blockStates, itemStacks);
return blockStates;
} }
if (m.mirrorY) { private static void blockStateMirrorX(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
placeMirrorY(event.getWorld(), event.getPlayer(), m, oldBlockPos, event.getPlacedBlock(), bagInventory, itemStack, event.getHand()); IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
}
if (m.mirrorZ) {
placeMirrorZ(event.getWorld(), event.getPlayer(), m, oldBlockPos, event.getPlacedBlock(), bagInventory, itemStack, event.getHand());
}
return true;
}
private static void placeMirrorX(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, EnumHand hand) {
//find mirror position //find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5); double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ()); BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
@@ -95,22 +116,22 @@ public class Mirror {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
if (itemStack.isEmpty()) return; oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
oldBlockState = getBlockStateFromRandomizerBag(bagInventory, world, player, oldBlockPos, itemStack, hand);
if (oldBlockState == null) return;
} }
IBlockState newBlockState = oldBlockState.withMirror(net.minecraft.util.Mirror.FRONT_BACK); //Find blockstate
//place block IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.withMirror(net.minecraft.util.Mirror.FRONT_BACK);
if (world.isBlockLoaded(newBlockPos, true)) {
placeBlock(world, player, newBlockPos, newBlockState, itemStack, hand); //Store blockstate and itemstack
} blockStates.add(newBlockState);
if (m.mirrorY) placeMirrorY(world, player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand); itemStacks.add(itemStack);
if (m.mirrorZ) placeMirrorZ(world, player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand);
if (m.mirrorY) blockStateMirrorY(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
if (m.mirrorZ) blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
} }
private static void placeMirrorY(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState, private static void blockStateMirrorY(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, EnumHand hand) { IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position //find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5); double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ()); BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
@@ -118,21 +139,21 @@ public class Mirror {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
if (itemStack.isEmpty()) return; oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
oldBlockState = getBlockStateFromRandomizerBag(bagInventory, world, player, oldBlockPos, itemStack, hand);
if (oldBlockState == null) return;
} }
IBlockState newBlockState = getVerticalMirror(oldBlockState); //Find blockstate
//place block IBlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState);
if (world.isBlockLoaded(newBlockPos, true)) {
placeBlock(world, player, newBlockPos, newBlockState, itemStack, hand); //Store blockstate and itemstack
} blockStates.add(newBlockState);
if (m.mirrorZ) placeMirrorZ(world, player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand); itemStacks.add(itemStack);
if (m.mirrorZ) blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
} }
private static void placeMirrorZ(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState, private static void blockStateMirrorZ(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, EnumHand hand) { IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position //find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z); BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
@@ -140,33 +161,27 @@ public class Mirror {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
if (itemStack.isEmpty()) return; oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
oldBlockState = getBlockStateFromRandomizerBag(bagInventory, world, player, oldBlockPos, itemStack, hand);
if (oldBlockState == null) return;
} }
IBlockState newBlockState = oldBlockState.withMirror(net.minecraft.util.Mirror.LEFT_RIGHT); //Find blockstate
//place block IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.withMirror(net.minecraft.util.Mirror.LEFT_RIGHT);
if (world.isBlockLoaded(newBlockPos, true)) {
placeBlock(world, player, newBlockPos, newBlockState, itemStack, hand); //Store blockstate and itemstack
} blockStates.add(newBlockState);
itemStacks.add(itemStack);
} }
private static IBlockState getBlockStateFromRandomizerBag(IItemHandler bagInventory, World world, EntityPlayer player, BlockPos pos, ItemStack itemStack, EnumHand hand) { public static boolean isEnabled(MirrorSettings m, BlockPos startPos) {
//TODO get facing from getPlacedAgainst and getPlacedBlock if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false;
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(world, pos, EnumFacing.NORTH, 0, 0, 0, itemStack.getMetadata(), player, hand);
}
private static void placeBlock(World world, EntityPlayer player, BlockPos newBlockPos, IBlockState newBlockState, ItemStack itemStack, EnumHand hand) { //if within mirror distance, mirror
//TODO check if can place if (startPos.getX() + 0.5 < m.position.x - m.radius || startPos.getX() + 0.5 > m.position.x + m.radius ||
//TODO check if can break startPos.getY() + 0.5 < m.position.y - m.radius || startPos.getY() + 0.5 > m.position.y + m.radius ||
startPos.getZ() + 0.5 < m.position.z - m.radius || startPos.getZ() + 0.5 > m.position.z + m.radius)
return false;
SurvivalHelper.placeBlock(world, player, newBlockPos, newBlockState, itemStack, EnumFacing.NORTH, true, false); return true;
//Array synergy
BlockSnapshot blockSnapshot = new BlockSnapshot(world, newBlockPos, newBlockState);
BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, newBlockState, player, hand);
Array.onBlockPlaced(placeEvent);
} }
private static IBlockState getVerticalMirror(IBlockState blockState) { private static IBlockState getVerticalMirror(IBlockState blockState) {
@@ -209,147 +224,4 @@ public class Mirror {
return blockState; return blockState;
} }
//Called from EventHandler
public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote) return;
//find mirrorsettings for the player that broke the block
MirrorSettings m = BuildSettingsManager.getBuildSettings(event.getPlayer()).getMirrorSettings();
if (m == null) return;
if (!m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return;
//if within mirror distance, break mirror block
BlockPos oldBlockPos = event.getPos();
if (oldBlockPos.getX() + 0.5 < m.position.x - m.radius || oldBlockPos.getX() + 0.5 > m.position.x + m.radius ||
oldBlockPos.getY() + 0.5 < m.position.y - m.radius || oldBlockPos.getY() + 0.5 > m.position.y + m.radius ||
oldBlockPos.getZ() + 0.5 < m.position.z - m.radius || oldBlockPos.getZ() + 0.5 > m.position.z + m.radius)
return;
if (m.mirrorX) {
breakMirrorX(event, m, oldBlockPos);
}
if (m.mirrorY) {
breakMirrorY(event, m, oldBlockPos);
}
if (m.mirrorZ) {
breakMirrorZ(event, m, oldBlockPos);
}
}
private static void breakMirrorX(BlockEvent.BreakEvent event, MirrorSettings m, BlockPos oldBlockPos) {
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
//break block
breakBlock(event, newBlockPos);
if (m.mirrorY) breakMirrorY(event, m, newBlockPos);
if (m.mirrorZ) breakMirrorZ(event, m, newBlockPos);
}
private static void breakMirrorY(BlockEvent.BreakEvent event, MirrorSettings m, BlockPos oldBlockPos) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
//break block
breakBlock(event, newBlockPos);
if (m.mirrorZ) breakMirrorZ(event, m, newBlockPos);
}
private static void breakMirrorZ(BlockEvent.BreakEvent event, MirrorSettings m, BlockPos oldBlockPos) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
//break block
breakBlock(event, newBlockPos);
}
private static void breakBlock(BlockEvent.BreakEvent event, BlockPos newBlockPos) {
if (!event.getWorld().isBlockLoaded(newBlockPos, false)) return;
SurvivalHelper.breakBlock(event.getWorld(), event.getPlayer(), newBlockPos);
//Array synergy
BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(event.getWorld(), newBlockPos, event.getWorld().getBlockState(newBlockPos), event.getPlayer());
Array.onBlockBroken(breakEvent);
}
//Called from EventHandler
public static float getTotalBlockHardness(World world, EntityPlayer player, BlockPos oldBlockPos) {
float hardness = 0;
//find mirrorsettings for the player that broke the block
MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings();
if (m == null) return 0;
if (!m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return 0;
//if within mirror distance, break mirror block
if (oldBlockPos.getX() + 0.5 < m.position.x - m.radius || oldBlockPos.getX() + 0.5 > m.position.x + m.radius ||
oldBlockPos.getY() + 0.5 < m.position.y - m.radius || oldBlockPos.getY() + 0.5 > m.position.y + m.radius ||
oldBlockPos.getZ() + 0.5 < m.position.z - m.radius || oldBlockPos.getZ() + 0.5 > m.position.z + m.radius)
return 0;
if (m.mirrorX) {
hardness += getHardnessX(world, player, m, oldBlockPos);
}
if (m.mirrorY) {
hardness += getHardnessY(world, player, m, oldBlockPos);
}
if (m.mirrorZ) {
hardness += getHardnessZ(world, player, m, oldBlockPos);
}
return hardness;
}
private static float getHardnessX(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos) {
float hardness = 0;
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
if (SurvivalHelper.canBreak(world, player, newBlockPos))
hardness += world.getBlockState(newBlockPos).getBlockHardness(world, newBlockPos);
if (m.mirrorY) hardness += getHardnessY(world, player, m, newBlockPos);
if (m.mirrorZ) hardness += getHardnessZ(world, player, m, newBlockPos);
return hardness;
}
private static float getHardnessY(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos) {
float hardness = 0;
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
if (SurvivalHelper.canBreak(world, player, newBlockPos))
hardness += world.getBlockState(newBlockPos).getBlockHardness(world, newBlockPos);
if (m.mirrorZ) hardness += getHardnessZ(world, player, m, newBlockPos);
return hardness;
}
private static float getHardnessZ(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos) {
float hardness = 0;
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
if (SurvivalHelper.canBreak(world, player, newBlockPos))
hardness += world.getBlockState(newBlockPos).getBlockHardness(world, newBlockPos);
return hardness;
}
} }

View File

@@ -1,74 +0,0 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.QuickReplaceMessage;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.UUID;
public class QuickReplace {
//Dilemma in getting blockstate from event to when message is received:
// 1) send via client. Then hacking makes it possible to place any block.
// 2) save serverside. Messages may not be received chronologically so data could get switched.
//Solution for now: save data serverside and per player. Messages from 1 player will rarely come unchronologically
//and players will rarely switch between blocks that quickly.
private static Dictionary<UUID, IBlockState> blockStates = new Hashtable<>();
private static Dictionary<UUID, ItemStack> itemStacks = new Hashtable<>();
private static Dictionary<UUID, EnumHand> hands = new Hashtable<>();
public static boolean onBlockPlaced(BlockEvent.PlaceEvent event) {
if (event.getWorld().isRemote) return true;
//Only serverside
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
if (!buildSettings.doQuickReplace()) return false;
//TODO base on player facing instead, no more messages (or break block clientside)
blockStates.put(event.getPlayer().getUniqueID(), event.getPlacedBlock());
itemStacks.put(event.getPlayer().getUniqueID(), event.getPlayer().getHeldItem(event.getHand()));
hands.put(event.getPlayer().getUniqueID(), event.getHand());
//RayTraceResult result = event.getWorld().rayTraceBlocks(event.getPlayer().getPositionEyes(1f), event.getPlayer().getLookVec());
EffortlessBuilding.packetHandler.sendTo(new QuickReplaceMessage(), (EntityPlayerMP) event.getPlayer());
return true;
}
public static void onMessageReceived(EntityPlayer player, QuickReplaceMessage message) {
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
if (!buildSettings.doQuickReplace()) return;
if (!message.isBlockHit() || message.getBlockPos() == null) return;
BlockPos placedAgainstBlockPos = message.getBlockPos();
//Get under tall grass and other replaceable blocks
if (player.world.getBlockState(placedAgainstBlockPos).getBlock().isReplaceable(player.world, placedAgainstBlockPos)) {
placedAgainstBlockPos = placedAgainstBlockPos.down();
}
IBlockState blockState = blockStates.get(player.getUniqueID());
ItemStack itemStack = itemStacks.get(player.getUniqueID());
EnumHand hand = hands.get(player.getUniqueID());
SurvivalHelper.placeBlock(player.world, player, placedAgainstBlockPos, blockState, itemStack, message.getSideHit(), true, false);
//Mirror and Array synergy
blockState = player.world.getBlockState(placedAgainstBlockPos);
BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, placedAgainstBlockPos, blockState);
BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
Mirror.onBlockPlaced(placeEvent);
Array.onBlockPlaced(placeEvent);
}
}

View File

@@ -19,18 +19,18 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class BuildModifierCapability { public class BuildModifierCapabilityManager {
@CapabilityInject(IBuildModifier.class) @CapabilityInject(IBuildModifierCapability.class)
public final static Capability<IBuildModifier> buildModifier = null; public final static Capability<IBuildModifierCapability> buildModifierCapability = null;
public interface IBuildModifier { public interface IBuildModifierCapability {
BuildSettings getBuildModifierData(); BuildSettings getBuildModifierData();
void setBuildModifierData(BuildSettings buildSettings); void setBuildModifierData(BuildSettings buildSettings);
} }
public static class BuildModifier implements IBuildModifier { public static class BuildModifierCapability implements IBuildModifierCapability {
private BuildSettings buildSettings; private BuildSettings buildSettings;
@Override @Override
@@ -44,9 +44,9 @@ public class BuildModifierCapability {
} }
} }
public static class Storage implements Capability.IStorage<IBuildModifier> { public static class Storage implements Capability.IStorage<IBuildModifierCapability> {
@Override @Override
public NBTBase writeNBT(Capability<IBuildModifier> capability, IBuildModifier instance, EnumFacing side) { public NBTBase writeNBT(Capability<IBuildModifierCapability> capability, IBuildModifierCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound(); NBTTagCompound compound = new NBTTagCompound();
BuildSettings buildSettings = instance.getBuildModifierData(); BuildSettings buildSettings = instance.getBuildModifierData();
if (buildSettings == null) buildSettings = new BuildSettings(); if (buildSettings == null) buildSettings = new BuildSettings();
@@ -79,7 +79,7 @@ public class BuildModifierCapability {
} }
@Override @Override
public void readNBT(Capability<IBuildModifier> capability, IBuildModifier instance, EnumFacing side, NBTBase nbt) { public void readNBT(Capability<IBuildModifierCapability> capability, IBuildModifierCapability instance, EnumFacing side, NBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt; NBTTagCompound compound = (NBTTagCompound) nbt;
//MIRROR //MIRROR
@@ -109,35 +109,35 @@ public class BuildModifierCapability {
} }
public static class Provider implements ICapabilitySerializable<NBTBase> { public static class Provider implements ICapabilitySerializable<NBTBase> {
IBuildModifier inst = buildModifier.getDefaultInstance(); IBuildModifierCapability inst = buildModifierCapability.getDefaultInstance();
@Override @Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) { public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
return capability == buildModifier; return capability == buildModifierCapability;
} }
@Override @Override
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) { public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
if (capability == buildModifier) return buildModifier.<T>cast(inst); if (capability == buildModifierCapability) return buildModifierCapability.<T>cast(inst);
return null; return null;
} }
@Override @Override
public NBTBase serializeNBT() { public NBTBase serializeNBT() {
return buildModifier.getStorage().writeNBT(buildModifier, inst, null); return buildModifierCapability.getStorage().writeNBT(buildModifierCapability, inst, null);
} }
@Override @Override
public void deserializeNBT(NBTBase nbt) { public void deserializeNBT(NBTBase nbt) {
buildModifier.getStorage().readNBT(buildModifier, inst, null, nbt); buildModifierCapability.getStorage().readNBT(buildModifierCapability, inst, null, nbt);
} }
} }
// Allows for the capability to persist after death. // Allows for the capability to persist after death.
@SubscribeEvent @SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) { public static void clonePlayer(PlayerEvent.Clone event) {
IBuildModifier original = event.getOriginal().getCapability(buildModifier, null); IBuildModifierCapability original = event.getOriginal().getCapability(buildModifierCapability, null);
IBuildModifier clone = event.getEntity().getCapability(buildModifier, null); IBuildModifierCapability clone = event.getEntity().getCapability(buildModifierCapability, null);
clone.setBuildModifierData(original.getBuildModifierData()); clone.setBuildModifierData(original.getBuildModifierData());
} }
} }

View File

@@ -0,0 +1,211 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
private GuiCheckBox buttonArrayEnabled;
private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount;
public ArraySettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
id = super.initGui(id, buttonList);
int y = top;
buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
buttonList.add(buttonArrayEnabled);
y = top + 20;
textArrayOffsetX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 70, y, 50, 18);
textArrayOffsetX.setNumber(0);
textArrayOffsetX.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetX);
textArrayOffsetY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 140, y, 50, 18);
textArrayOffsetY.setNumber(0);
textArrayOffsetY.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetY);
textArrayOffsetZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 210, y, 50, 18);
textArrayOffsetZ.setNumber(0);
textArrayOffsetZ.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetZ);
y = top + 50;
textArrayCount = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 55, y, 50, 18);
textArrayCount.setNumber(5);
textArrayCount.setTooltip("How many copies should be made.");
arrayNumberFieldList.add(textArrayCount);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (buildSettings != null) {
Array.ArraySettings a = buildSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY());
textArrayOffsetZ.setNumber(a.offset.getZ());
textArrayCount.setNumber(a.count);
}
setCollapsed(!buttonArrayEnabled.isChecked());
return id;
}
@Override
public void updateScreen() {
super.updateScreen();
arrayNumberFieldList.forEach(GuiNumberField::update);
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partialTicks);
int yy = y;
int offset = 8;
buttonArrayEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonArrayEnabled.isChecked()) {
buttonArrayEnabled.y = yy;
fontRenderer.drawString("Array enabled", left + offset, yy + 2, 0xFFFFFF, true);
yy = y + 20;
fontRenderer.drawString("Offset", left + offset, yy + 5, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 50 + offset, yy + 5, 0xFFFFFF, true);
textArrayOffsetX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF, true);
textArrayOffsetY.y = yy;
fontRenderer.drawString("Z", left + 190 + offset, yy + 5, 0xFFFFFF, true);
textArrayOffsetZ.y = yy;
yy = y + 50;
fontRenderer.drawString("Count", left + offset, yy + 5, 0xFFFFFF, true);
textArrayCount.y = yy;
int currentReach = Math.max(-1, getArrayReach());
int maxReach = BuildSettingsManager.getMaxReach(mc.player);
TextFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? TextFormatting.GRAY : TextFormatting.RED;
String reachText = "Reach: " + reachColor + currentReach + TextFormatting.GRAY + "/" + TextFormatting.GRAY + maxReach;
fontRenderer.drawString(reachText, left + 176 + offset, yy + 5, 0xFFFFFF, true);
arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else {
buttonArrayEnabled.y = yy;
fontRenderer.drawString("Array disabled", left + offset, yy + 2, 0x999999, true);
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonArrayEnabled.isChecked())
{
arrayNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
@Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
super.updatePosition(slotIndex, x, y, partialTicks);
}
@Override
public void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
for (GuiNumberField numberField : arrayNumberFieldList) {
numberField.keyTyped(typedChar, keyCode);
}
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
super.mousePressed(slotIndex, mouseX, mouseY, mouseEvent, relativeX, relativeY);
arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideArrayEnabledLabel) {
buttonArrayEnabled.setIsChecked(!buttonArrayEnabled.isChecked());
buttonArrayEnabled.playPressSound(this.mc.getSoundHandler());
actionPerformed(buttonArrayEnabled);
}
return true;
}
@Override
public void actionPerformed(GuiButton button) {
super.actionPerformed(button);
if (button == buttonArrayEnabled) {
setCollapsed(!buttonArrayEnabled.isChecked());
}
arrayNumberFieldList.forEach(numberField -> numberField.actionPerformed(button));
}
public Array.ArraySettings getArraySettings() {
boolean arrayEnabled = buttonArrayEnabled.isChecked();
BlockPos arrayOffset = new BlockPos(0, 0, 0);
try {
arrayOffset = new BlockPos(textArrayOffsetX.getNumber(), textArrayOffsetY.getNumber(), textArrayOffsetZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array offset not valid.");
}
int arrayCount = 5;
try {
arrayCount = (int) textArrayCount.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array count not valid.");
}
return new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
}
@Override
protected String getName() {
return "Array";
}
@Override
protected int getExpandedHeight() {
return 80;
}
private int getArrayReach() {
try
{
//find largest offset
double x = Math.abs(textArrayOffsetX.getNumber());
double y = Math.abs(textArrayOffsetY.getNumber());
double z = Math.abs(textArrayOffsetZ.getNumber());
double largestOffset = Math.max(Math.max(x, y), z);
return (int) (largestOffset * textArrayCount.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
return -1;
}
}
private boolean isCurrentReachValid(int currentReach, int maxReach) {
return currentReach <= maxReach && currentReach > -1;
}
}

View File

@@ -0,0 +1,103 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import java.io.IOException;
import java.util.List;
public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScrollEntry {
public GuiScrollPane scrollPane;
protected FontRenderer fontRenderer;
protected Minecraft mc;
protected boolean isCollapsed = true;
protected int left, right, top, bottom;
public GuiCollapsibleScrollEntry(GuiScrollPane scrollPane) {
this.scrollPane = scrollPane;
this.fontRenderer = scrollPane.fontRenderer;
this.mc = scrollPane.parent.mc;
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
left = scrollPane.width / 2 - 140;
right = scrollPane.width / 2 + 140;
top = scrollPane.height / 2 - 100;
bottom = scrollPane.height / 2 + 100;
return id;
}
@Override
public void updateScreen() {
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
}
@Override
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
}
@Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
}
@Override
public void keyTyped(char eventChar, int eventKey) throws IOException {
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
return false;
}
@Override
public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) {
}
@Override
public void actionPerformed(GuiButton button) {
}
@Override
public void onGuiClosed() {
}
@Override
public int getHeight() {
return isCollapsed ? getCollapsedHeight() : getExpandedHeight();
}
public void setCollapsed(boolean collapsed) {
this.isCollapsed = collapsed;
}
protected String getName() {
return "Collapsible scroll entry";
}
protected int getCollapsedHeight() {
return 24;
}
protected int getExpandedHeight() {
return 100;
}
}

View File

@@ -73,6 +73,10 @@ public class GuiNumberField extends Gui {
} }
public void drawNumberField(Minecraft mc, int mouseX, int mouseY, float partialTicks) { public void drawNumberField(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
textField.y = y + 1;
minusButton.y = y - 1;
plusButton.y = y - 1;
textField.drawTextBox(); textField.drawTextBox();
minusButton.drawButton(mc, mouseX, mouseY, partialTicks); minusButton.drawButton(mc, mouseX, mouseY, partialTicks);
plusButton.drawButton(mc, mouseX, mouseY, partialTicks); plusButton.drawButton(mc, mouseX, mouseY, partialTicks);
@@ -131,19 +135,20 @@ public class GuiNumberField extends Gui {
// } // }
} }
public void handleMouseInput(int mouseX, int mouseY) { //Scroll inside textfield to change number
boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height; // public void handleMouseInput(int mouseX, int mouseY) {
// boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
if (insideTextField) //
{ // if (insideTextField)
int valueChanged = 0; // {
if (Mouse.getEventDWheel() > 0) // int valueChanged = 0;
valueChanged = 1; // if (Mouse.getEventDWheel() > 0)
if (Mouse.getEventDWheel() < 0) // valueChanged = 1;
valueChanged = -1; // if (Mouse.getEventDWheel() < 0)
// valueChanged = -1;
if (valueChanged != 0) //
setNumber(getNumber() + valueChanged); // if (valueChanged != 0)
} // setNumber(getNumber() + valueChanged);
} // }
// }
} }

View File

@@ -0,0 +1,435 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiListExtended;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.input.Mouse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@SideOnly(Side.CLIENT)
public class GuiScrollPane extends GuiListExtended {
public GuiScreen parent;
public FontRenderer fontRenderer;
public List<IScrollEntry> listEntries;
public GuiScrollPane(GuiScreen parent, FontRenderer fontRenderer, int top, int bottom) {
super(parent.mc, parent.width, parent.height, top, bottom, 100);
this.parent = parent;
this.fontRenderer = fontRenderer;
this.setShowSelectionBox(false);
listEntries = new ArrayList<>();
}
@Override
public IGuiListEntry getListEntry(int index) {
return listEntries.get(index);
}
@Override
protected int getSize() {
return listEntries.size();
}
@Override
protected int getScrollBarX() {
//return width / 2 + 140 + 10;
return width - 15;
}
@Override
public int getListWidth() {
return 280;
}
//Removed background
@Override
public void drawScreen(int mouseXIn, int mouseYIn, float partialTicks)
{
if (this.visible)
{
this.mouseX = mouseXIn;
this.mouseY = mouseYIn;
int scrollBarLeft = this.getScrollBarX();
int scrollBarRight = scrollBarLeft + 6;
this.bindAmountScrolled();
GlStateManager.disableLighting();
GlStateManager.disableFog();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
int insideLeft = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
int insideTop = this.top + 4 - (int)this.amountScrolled;
if (this.hasListHeader)
{
this.drawListHeader(insideLeft, insideTop, tessellator);
}
//All entries
this.drawSelectionBox(insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks);
GlStateManager.disableDepth();
//Dirt overlays on top and bottom
// this.overlayBackground(0, this.top, 255, 255);
// this.overlayBackground(this.bottom, this.height, 255, 255);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
GlStateManager.disableAlpha();
GlStateManager.shadeModel(7425);
GlStateManager.disableTexture2D();
// //top fade
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)(this.top + 5), 0.0D).tex(0.0D, 1.0D).color(100, 100, 100, 0).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.top + 5), 0.0D).tex(1.0D, 1.0D).color(100, 100, 100, 0).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.top, 0.0D).tex(1.0D, 0.0D).color(100, 100, 100, 100).endVertex();
// bufferbuilder.pos((double)this.left, (double)this.top, 0.0D).tex(0.0D, 0.0D).color(100, 100, 100, 100).endVertex();
// tessellator.draw();
// //top line
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)this.top, 0.0D).tex(0.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.top, 0.0D).tex(1.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.top - 1), 0.0D).tex(1.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.left, (double)(this.top - 1), 0.0D).tex(0.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// tessellator.draw();
// //bottom fade
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)this.bottom, 0.0D).tex(0.0D, 1.0D).color(10, 10, 10, 100).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.bottom, 0.0D).tex(1.0D, 1.0D).color(10, 10, 10, 100).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.bottom - 5), 0.0D).tex(1.0D, 0.0D).color(10, 10, 10, 0).endVertex();
// bufferbuilder.pos((double)this.left, (double)(this.bottom - 5), 0.0D).tex(0.0D, 0.0D).color(10, 10, 10, 0).endVertex();
// tessellator.draw();
// //bottom line
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)(this.bottom + 1), 0.0D).tex(0.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.bottom + 1), 0.0D).tex(1.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.bottom, 0.0D).tex(1.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.left, (double)this.bottom, 0.0D).tex(0.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// tessellator.draw();
//Draw scrollbar
int maxScroll = this.getMaxScroll();
if (maxScroll > 0)
{
int k1 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
k1 = MathHelper.clamp(k1, 32, this.bottom - this.top - 8);
int l1 = (int)this.amountScrolled * (this.bottom - this.top - k1) / maxScroll + this.top;
if (l1 < this.top)
{
l1 = this.top;
}
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)scrollBarLeft, (double)this.bottom, 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)this.bottom, 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)this.top, 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)scrollBarLeft, (double)this.top, 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex();
tessellator.draw();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)scrollBarLeft, (double)(l1 + k1), 0.0D).tex(0.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)(l1 + k1), 0.0D).tex(1.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)l1, 0.0D).tex(1.0D, 0.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)scrollBarLeft, (double)l1, 0.0D).tex(0.0D, 0.0D).color(128, 128, 128, 255).endVertex();
tessellator.draw();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)scrollBarLeft, (double)(l1 + k1 - 1), 0.0D).tex(0.0D, 1.0D).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)(scrollBarRight - 1), (double)(l1 + k1 - 1), 0.0D).tex(1.0D, 1.0D).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)(scrollBarRight - 1), (double)l1, 0.0D).tex(1.0D, 0.0D).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)scrollBarLeft, (double)l1, 0.0D).tex(0.0D, 0.0D).color(192, 192, 192, 255).endVertex();
tessellator.draw();
}
GlStateManager.enableTexture2D();
GlStateManager.shadeModel(7424);
GlStateManager.enableAlpha();
GlStateManager.disableBlend();
}
}
//SLOTHEIGHT MODIFICATIONS
//SlotHeight is still relied on for determining how much to scroll
@Override
protected int getContentHeight() {
//Add every entry height
int height = this.headerPadding;
for (IScrollEntry entry : listEntries) {
height += entry.getHeight();
}
return height;
}
public int getContentHeight(int count) {
//Add all count entry heights
int height = this.headerPadding;
for (int i = 0; i < count; i++) {
IScrollEntry entry = listEntries.get(i);
height += entry.getHeight();
}
return height;
}
@Override
public int getSlotIndexFromScreenCoords(int posX, int posY) {
int left = this.left + (this.width - this.getListWidth()) / 2;
int right = this.left + (this.width + this.getListWidth()) / 2;
int relativeMouseY = posY - this.top - this.headerPadding + (int)this.amountScrolled - 4; //click height in content dimensions
//int slotIndex = relativeMouseY / this.slotHeight;
//Iterate over every entry until relativeMouseY falls within its height
for (int i = 0; i < listEntries.size(); i++) {
IScrollEntry entry = listEntries.get(i);
if (relativeMouseY <= entry.getHeight())
return posX < this.getScrollBarX() && posX >= left && posX <= right && i >= 0 &&
relativeMouseY >= 0 && i < this.getSize() ? i : -1;
relativeMouseY -= entry.getHeight();
}
return -1;
}
@Override
public boolean mouseClicked(int mouseX, int mouseY, int mouseEvent)
{
if (this.isMouseYWithinSlotBounds(mouseY))
{
int i = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
if (i >= 0)
{
int j = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
int k = this.top + 4 - this.getAmountScrolled() + getContentHeight(i) + this.headerPadding;
int relativeX = mouseX - j;
int relativeY = mouseY - k;
if (this.getListEntry(i).mousePressed(i, mouseX, mouseY, mouseEvent, relativeX, relativeY))
{
this.setEnabled(false);
return true;
}
}
}
return false;
}
@Override
public boolean mouseReleased(int x, int y, int mouseEvent)
{
for (int i = 0; i < this.getSize(); ++i)
{
int j = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
int k = this.top + 4 - this.getAmountScrolled() + getContentHeight(i) + this.headerPadding;
int relativeX = x - j;
int relativeY = y - k;
this.getListEntry(i).mouseReleased(i, x, y, mouseEvent, relativeX, relativeY);
}
this.setEnabled(true);
return false;
}
@Override
public void handleMouseInput() {
if (this.isMouseYWithinSlotBounds(this.mouseY)) {
if (Mouse.getEventButton() == 0 && Mouse.getEventButtonState() && this.mouseY >= this.top &&
this.mouseY <= this.bottom) {
int i = this.left + (this.width - this.getListWidth()) / 2;
int j = this.left + (this.width + this.getListWidth()) / 2;
int relativeMouseY = this.mouseY - this.top - this.headerPadding + (int) this.amountScrolled -
4; //click height in content dimensions
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
if (slotIndex > -1) {
this.elementClicked(slotIndex, false, this.mouseX, this.mouseY);
this.selectedElement = slotIndex;
} else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i, this.mouseY - this.top + (int) this.amountScrolled - 4);
}
}
if (Mouse.isButtonDown(0) && this.getEnabled()) {
if (this.initialClickY == -1) {
boolean flag1 = true;
if (this.mouseY >= this.top && this.mouseY <= this.bottom) {
int i2 = this.left + (this.width - this.getListWidth()) / 2;
int j2 = this.left + (this.width + this.getListWidth()) / 2;
int relativeMouseY = this.mouseY - this.top - this.headerPadding + (int) this.amountScrolled -
4; //click height in content dimensions
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
if (slotIndex > -1) {
boolean flag = slotIndex == this.selectedElement &&
Minecraft.getSystemTime() - this.lastClicked < 250L;
this.elementClicked(slotIndex, flag, this.mouseX, this.mouseY);
this.selectedElement = slotIndex;
this.lastClicked = Minecraft.getSystemTime();
} else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i2,
this.mouseY - this.top + (int) this.amountScrolled - 4);
flag1 = false;
}
int i3 = this.getScrollBarX();
int j1 = i3 + 6;
if (this.mouseX >= i3 && this.mouseX <= j1) {
this.scrollMultiplier = -1.0F;
int maxScroll = this.getMaxScroll();
if (maxScroll < 1) {
maxScroll = 1;
}
int l1 = (int) ((float) ((this.bottom - this.top) * (this.bottom - this.top)) /
(float) this.getContentHeight());
l1 = MathHelper.clamp(l1, 32, this.bottom - this.top - 8);
this.scrollMultiplier /= (float) (this.bottom - this.top - l1) / (float) maxScroll;
} else {
this.scrollMultiplier = 1.0F;
}
if (flag1) {
this.initialClickY = this.mouseY;
} else {
this.initialClickY = -2;
}
} else {
this.initialClickY = -2;
}
} else if (this.initialClickY >= 0) {
this.amountScrolled -= (float) (this.mouseY - this.initialClickY) * this.scrollMultiplier;
this.initialClickY = this.mouseY;
}
} else {
this.initialClickY = -1;
}
int i2 = Mouse.getEventDWheel();
if (i2 != 0) {
if (i2 > 0) {
i2 = -1;
} else if (i2 < 0) {
i2 = 1;
}
this.amountScrolled += (float) (i2 * this.slotHeight / 2);
}
}
}
//Draw in center if it fits
@Override
protected void drawSelectionBox(int insideLeft, int insideTop, int mouseXIn, int mouseYIn, float partialTicks)
{
int size = this.getSize();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
//Find y to start with
int y = this.headerPadding + insideTop;
int contentHeight = getContentHeight();
int insideHeight = this.bottom - this.top - 4;
if (contentHeight < insideHeight) {
//it fits, so we can center it vertically
y += (insideHeight - contentHeight) / 2;
}
//Draw all entries
for (int i = 0; i < size; ++i)
{
int entryHeight = listEntries.get(i).getHeight();
int entryHeight2 = entryHeight - 4;
if (y > this.bottom || y + entryHeight2 < this.top)
{
this.updateItemPos(i, insideLeft, y, partialTicks);
}
if (this.showSelectionBox && this.isSelected(i))
{
int i1 = this.left + this.width / 2 - this.getListWidth() / 2;
int j1 = this.left + this.width / 2 + this.getListWidth() / 2;
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableTexture2D();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)i1, (double)(y + entryHeight2 + 2), 0.0D).tex(0.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)j1, (double)(y + entryHeight2 + 2), 0.0D).tex(1.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)j1, (double)(y - 2), 0.0D).tex(1.0D, 0.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)i1, (double)(y - 2), 0.0D).tex(0.0D, 0.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)(i1 + 1), (double)(y + entryHeight2 + 1), 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)(j1 - 1), (double)(y + entryHeight2 + 1), 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)(j1 - 1), (double)(y - 1), 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)(i1 + 1), (double)(y - 1), 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex();
tessellator.draw();
GlStateManager.enableTexture2D();
}
this.drawSlot(i, insideLeft, y, entryHeight2, mouseXIn, mouseYIn, partialTicks);
y += entryHeight;
}
}
//PASSTHROUGHS
public int initGui(int id, List<GuiButton> buttonList) {
for (IScrollEntry entry : this.listEntries) {
id = entry.initGui(id, buttonList);
}
registerScrollButtons(id++, id++);
return id;
}
public void updateScreen() {
for (IScrollEntry entry : this.listEntries)
entry.updateScreen();
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
for (IScrollEntry entry : this.listEntries)
entry.drawTooltip(guiScreen, mouseX, mouseY);
}
public void keyTyped(char eventChar, int eventKey) throws IOException {
for (IScrollEntry entry : this.listEntries)
entry.keyTyped(eventChar, eventKey);
}
public void actionPerformed(GuiButton button) {
for (IScrollEntry entry : this.listEntries)
entry.actionPerformed(button);
}
public void onGuiClosed() {
for (IScrollEntry entry : this.listEntries)
entry.onGuiClosed();
}
public interface IScrollEntry extends GuiListExtended.IGuiListEntry {
int initGui(int id, List<GuiButton> buttonList);
void updateScreen();
void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY);
void keyTyped(char eventChar, int eventKey) throws IOException;
void actionPerformed(GuiButton button);
void onGuiClosed();
int getHeight();
}
}

View File

@@ -0,0 +1,294 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.Mirror;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected List<GuiButton> mirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> mirrorNumberFieldList = new ArrayList<>();
private GuiNumberField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius;
private GuiCheckBox buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
public MirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
id = super.initGui(id, buttonList);
int y = top - 2;
buttonMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
buttonList.add(buttonMirrorEnabled);
y = top + 18;
textMirrorPosX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 58, y, 62, 18);
textMirrorPosX.setNumber(0);
textMirrorPosX.setTooltip(
Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosX);
textMirrorPosY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 138, y, 62, 18);
textMirrorPosY.setNumber(64);
textMirrorPosY.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosY);
textMirrorPosZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textMirrorPosZ.setNumber(0);
textMirrorPosZ.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosZ);
y = top + 50;
buttonMirrorX = new GuiCheckBox(id++, left + 60, y, " X", true);
mirrorButtonList.add(buttonMirrorX);
buttonMirrorY = new GuiCheckBox(id++, left + 100, y, " Y", false);
mirrorButtonList.add(buttonMirrorY);
buttonMirrorZ = new GuiCheckBox(id++, left + 140, y, " Z", false);
mirrorButtonList.add(buttonMirrorZ);
y = top + 47;
textMirrorRadius = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textMirrorRadius.setTooltip(Arrays.asList("How far the mirror reaches in any direction.",
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + BuildSettingsManager.getMaxReach(mc.player) / 2,
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades."));
mirrorNumberFieldList.add(textMirrorRadius);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS);
buttonCurrentPosition.setTooltip("Set mirror position to current player position");
mirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS);
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
mirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS);
buttonDrawLines.setTooltip("Show lines");
mirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS);
buttonDrawPlanes.setTooltip("Show area");
mirrorIconButtonList.add(buttonDrawPlanes);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (buildSettings != null) {
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y);
textMirrorPosZ.setNumber(m.position.z);
buttonMirrorX.setIsChecked(m.mirrorX);
buttonMirrorY.setIsChecked(m.mirrorY);
buttonMirrorZ.setIsChecked(m.mirrorZ);
textMirrorRadius.setNumber(m.radius);
drawLines = m.drawLines;
drawPlanes = m.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
if (textMirrorPosX.getNumber() == Math.floor(textMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
}
buttonList.addAll(mirrorButtonList);
buttonList.addAll(mirrorIconButtonList);
setCollapsed(!buttonMirrorEnabled.isChecked());
return id;
}
@Override
public void updateScreen() {
super.updateScreen();
mirrorNumberFieldList.forEach(GuiNumberField::update);
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partialTicks);
int yy = y;
int offset = 8;
buttonMirrorEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonMirrorEnabled.isChecked()) {
buttonMirrorEnabled.y = yy;
fontRenderer.drawString("Mirror enabled", left + offset, yy + 2, 0xFFFFFF, true);
yy = y + 18;
fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF, true);
textMirrorPosX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF, true);
textMirrorPosY.y = yy;
fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF, true);
textMirrorPosZ.y = yy;
yy = y + 50;
fontRenderer.drawString("Direction", left + offset, yy + 2, 0xFFFFFF, true);
buttonMirrorX.y = yy;
buttonMirrorY.y = yy;
buttonMirrorZ.y = yy;
fontRenderer.drawString("Reach", left + 176 + offset, yy + 2, 0xFFFFFF, true);
textMirrorRadius.y = yy - 3;
yy = y + 72;
buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
mirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorIconButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else {
buttonMirrorEnabled.y = yy;
fontRenderer.drawString("Mirror disabled", left + offset, yy + 2, 0x999999, true);
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonMirrorEnabled.isChecked())
{
mirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(scrollPane.parent, mouseX, mouseY));
mirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
@Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
super.updatePosition(slotIndex, x, y, partialTicks);
}
@Override
public void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
for (GuiNumberField numberField : mirrorNumberFieldList) {
numberField.keyTyped(typedChar, keyCode);
}
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
super.mousePressed(slotIndex, mouseX, mouseY, mouseEvent, relativeX, relativeY);
mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideMirrorEnabledLabel) {
buttonMirrorEnabled.setIsChecked(!buttonMirrorEnabled.isChecked());
buttonMirrorEnabled.playPressSound(this.mc.getSoundHandler());
actionPerformed(buttonMirrorEnabled);
}
return true;
}
@Override
public void actionPerformed(GuiButton button) {
super.actionPerformed(button);
if (button == buttonMirrorEnabled) {
setCollapsed(!buttonMirrorEnabled.isChecked());
}
if (button == buttonCurrentPosition) {
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z);
}
if (button == buttonToggleOdd) {
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
}
}
if (button == buttonDrawLines) {
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
if (button == buttonDrawPlanes) {
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
mirrorNumberFieldList.forEach(numberField -> numberField.actionPerformed(button));
}
public Mirror.MirrorSettings getMirrorSettings() {
boolean mirrorEnabled = buttonMirrorEnabled.isChecked();
Vec3d mirrorPos = new Vec3d(0, 64, 0);
try {
mirrorPos = new Vec3d(textMirrorPosX.getNumber(), textMirrorPosY.getNumber(), textMirrorPosZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror position not valid.");
}
boolean mirrorX = buttonMirrorX.isChecked();
boolean mirrorY = buttonMirrorY.isChecked();
boolean mirrorZ = buttonMirrorZ.isChecked();
int mirrorRadius = 50;
try {
mirrorRadius = (int) textMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not valid.");
}
return new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes);
}
@Override
protected String getName() {
return "Mirror";
}
@Override
protected int getExpandedHeight() {
return 100;
}
}

View File

@@ -2,190 +2,49 @@ package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.Array; import nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.BuildSettingsManager; import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.Mirror; import nl.requios.effortlessbuilding.Mirror;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.input.Mouse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SettingsGui extends GuiScreen { public class SettingsGui extends GuiScreen {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); private GuiScrollPane scrollPane;
protected List<GuiNumberField> numberFieldList = new ArrayList<>();
protected List<GuiButton> mirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> mirrorNumberFieldList = new ArrayList<>();
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
private GuiNumberField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius;
private GuiCheckBox buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
private GuiButton buttonClose; private GuiButton buttonClose;
private GuiCheckBox buttonArrayEnabled; private MirrorSettingsGui mirrorSettingsGui;
private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount; private ArraySettingsGui arraySettingsGui;
private int left, right, top, bottom;
@Override @Override
//Create buttons and labels and add them to buttonList/labelList //Create buttons and labels and add them to buttonList/labelList
public void initGui() { public void initGui() {
int id = 0; int id = 0;
left = width / 2 - 140;
right = width / 2 + 140;
top = height / 2 - 100;
bottom = height / 2 + 100;
//MIRROR scrollPane = new GuiScrollPane(this, fontRenderer, 8, height - 30);
int y = top - 2;
buttonMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
buttonList.add(buttonMirrorEnabled);
y = top + 18; mirrorSettingsGui = new MirrorSettingsGui(scrollPane);
textMirrorPosX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 58, y, 62, 18); scrollPane.listEntries.add(mirrorSettingsGui);
textMirrorPosX.setNumber(0);
textMirrorPosX.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosX);
textMirrorPosY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 138, y, 62, 18); arraySettingsGui = new ArraySettingsGui(scrollPane);
textMirrorPosY.setNumber(64); scrollPane.listEntries.add(arraySettingsGui);
textMirrorPosY.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosY);
textMirrorPosZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18); id = scrollPane.initGui(id, buttonList);
textMirrorPosZ.setNumber(0);
textMirrorPosZ.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosZ);
y = top + 50; //Close button
buttonMirrorX = new GuiCheckBox(id++, left + 60, y, " X", true); int y = height - 26;
mirrorButtonList.add(buttonMirrorX);
buttonMirrorY = new GuiCheckBox(id++, left + 100, y, " Y", false);
mirrorButtonList.add(buttonMirrorY);
buttonMirrorZ = new GuiCheckBox(id++, left + 140, y, " Z", false);
mirrorButtonList.add(buttonMirrorZ);
y = top + 47;
textMirrorRadius = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textMirrorRadius.setTooltip(Arrays.asList("How far the mirror reaches in any direction.",
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + BuildSettingsManager.getMaxReach(mc.player) / 2,
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades."));
mirrorNumberFieldList.add(textMirrorRadius);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS);
buttonCurrentPosition.setTooltip("Set mirror position to current player position");
mirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS);
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
mirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS);
buttonDrawLines.setTooltip("Show lines");
mirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS);
buttonDrawPlanes.setTooltip("Show area");
mirrorIconButtonList.add(buttonDrawPlanes);
//ARRAY
y = top + 100;
buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
buttonList.add(buttonArrayEnabled);
y = top + 120;
textArrayOffsetX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 70, y, 50, 18);
textArrayOffsetX.setNumber(0);
textArrayOffsetX.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetX);
textArrayOffsetY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 140, y, 50, 18);
textArrayOffsetY.setNumber(0);
textArrayOffsetY.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetY);
textArrayOffsetZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 210, y, 50, 18);
textArrayOffsetZ.setNumber(0);
textArrayOffsetZ.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetZ);
y = top + 150;
textArrayCount = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 55, y, 50, 18);
textArrayCount.setNumber(5);
textArrayCount.setTooltip("How many copies should be made.");
arrayNumberFieldList.add(textArrayCount);
//CLOSE
y = height - 40;
buttonClose = new GuiButton(id++, width / 2 - 100, y, "Close"); buttonClose = new GuiButton(id++, width / 2 - 100, y, "Close");
buttonList.add(buttonClose); buttonList.add(buttonClose);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (buildSettings != null) {
//MIRROR
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y);
textMirrorPosZ.setNumber(m.position.z);
buttonMirrorX.setIsChecked(m.mirrorX);
buttonMirrorY.setIsChecked(m.mirrorY);
buttonMirrorZ.setIsChecked(m.mirrorZ);
textMirrorRadius.setNumber(m.radius);
drawLines = m.drawLines;
drawPlanes = m.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
if (textMirrorPosX.getNumber() == Math.floor(textMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
//ARRAY
Array.ArraySettings a = buildSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY());
textArrayOffsetZ.setNumber(a.offset.getZ());
textArrayCount.setNumber(a.count);
}
buttonList.addAll(mirrorButtonList);
buttonList.addAll(mirrorIconButtonList);
numberFieldList.addAll(mirrorNumberFieldList);
numberFieldList.addAll(arrayNumberFieldList);
} }
@Override @Override
//Process general logic, i.e. hide buttons //Process general logic, i.e. hide buttons
public void updateScreen() { public void updateScreen() {
numberFieldList.forEach(GuiNumberField::update); scrollPane.updateScreen();
} }
@Override @Override
@@ -194,75 +53,17 @@ public class SettingsGui extends GuiScreen {
public void drawScreen(int mouseX, int mouseY, float partialTicks) { public void drawScreen(int mouseX, int mouseY, float partialTicks) {
this.drawDefaultBackground(); this.drawDefaultBackground();
int y = top; scrollPane.drawScreen(mouseX, mouseY, partialTicks);
int offset = 8;
buttonMirrorEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonMirrorEnabled.isChecked()) {
fontRenderer.drawString("Mirror enabled", left + offset, y, 0xFFFFFF, true);
y = top + 18 + 5;
fontRenderer.drawString("Position", left + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 40 + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("Y", left + 120 + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("Z", left + 200 + offset, y, 0xFFFFFF, true);
y = top + 52;
fontRenderer.drawString("Direction", left + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("Reach", left + 176 + offset, y, 0xFFFFFF, true);
mirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorIconButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else {
fontRenderer.drawString("Mirror disabled", left + offset, y, 0x999999, true);
}
y = top + 100 + 2;
buttonArrayEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonArrayEnabled.isChecked()) {
fontRenderer.drawString("Array enabled", left + offset, y, 0xFFFFFF, true);
y = top + 120 + 5;
fontRenderer.drawString("Offset", left + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 50 + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("Y", left + 120 + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("Z", left + 190 + offset, y, 0xFFFFFF, true);
y = top + 150 + 5;
fontRenderer.drawString("Count", left + offset, y, 0xFFFFFF, true);
int currentReach = Math.max(-1, getArrayReach());
int maxReach = BuildSettingsManager.getMaxReach(mc.player);
TextFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? TextFormatting.GRAY : TextFormatting.RED;
String reachText = "Reach: " + reachColor + currentReach + TextFormatting.GRAY + "/" + TextFormatting.GRAY + maxReach;
fontRenderer.drawString(reachText, left + 176 + offset, y, 0xFFFFFF, true);
arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else {
fontRenderer.drawString("Array disabled", left + offset, y, 0x999999, true);
}
buttonClose.drawButton(this.mc, mouseX, mouseY, partialTicks); buttonClose.drawButton(this.mc, mouseX, mouseY, partialTicks);
//Draw tooltips last scrollPane.drawTooltip(this, mouseX, mouseY);
if (buttonMirrorEnabled.isChecked())
{
mirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(this, mouseX, mouseY));
mirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(this, mouseX, mouseY));
}
if (buttonArrayEnabled.isChecked())
{
arrayNumberFieldList.forEach(numberField -> numberField.drawTooltip(this, mouseX, mouseY));
}
} }
@Override @Override
protected void keyTyped(char typedChar, int keyCode) throws IOException { protected void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode); super.keyTyped(typedChar, keyCode);
for (GuiNumberField numberField : numberFieldList) { scrollPane.keyTyped(typedChar, keyCode);
numberField.keyTyped(typedChar, keyCode);
}
if (keyCode == ClientProxy.keyBindings[0].getKeyCode()) { if (keyCode == ClientProxy.keyBindings[0].getKeyCode()) {
mc.player.closeScreen(); mc.player.closeScreen();
} }
@@ -271,116 +72,44 @@ public class SettingsGui extends GuiScreen {
@Override @Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton); super.mouseClicked(mouseX, mouseY, mouseButton);
numberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseButton)); scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && mouseY >= top - 2 && mouseY < top + 10;
boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && mouseY >= top + 100 && mouseY < top + 112;
if (insideMirrorEnabledLabel) {
buttonMirrorEnabled.setIsChecked(!buttonMirrorEnabled.isChecked());
buttonMirrorEnabled.playPressSound(this.mc.getSoundHandler());
actionPerformed(buttonMirrorEnabled);
} }
if (insideArrayEnabledLabel) { @Override
buttonArrayEnabled.setIsChecked(!buttonArrayEnabled.isChecked()); protected void mouseReleased(int mouseX, int mouseY, int state) {
buttonArrayEnabled.playPressSound(this.mc.getSoundHandler()); if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state))
actionPerformed(buttonArrayEnabled); {
super.mouseReleased(mouseX, mouseY, state);
} }
} }
@Override @Override
public void handleMouseInput() throws IOException { public void handleMouseInput() throws IOException {
super.handleMouseInput(); super.handleMouseInput();
int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth; scrollPane.handleMouseInput();
int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY)); //Scrolling numbers
// int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
// int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
// numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY));
} }
@Override @Override
protected void actionPerformed(GuiButton button) throws IOException { protected void actionPerformed(GuiButton button) {
//check what button and action type (left/right click) //check what button and action type (left/right click)
if (button == buttonClose) { if (button == buttonClose) {
mc.player.closeScreen(); mc.player.closeScreen();
} }
if (button == buttonCurrentPosition) { scrollPane.actionPerformed(button);
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z);
}
if (button == buttonToggleOdd) {
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
}
}
if (button == buttonDrawLines) {
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
if (button == buttonDrawPlanes) {
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
numberFieldList.forEach(numberField -> numberField.actionPerformed(button));
} }
@Override @Override
public void onGuiClosed() { public void onGuiClosed() {
scrollPane.onGuiClosed();
//save everything //save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings();
//MIRROR Array.ArraySettings a = arraySettingsGui.getArraySettings();
boolean mirrorEnabled = buttonMirrorEnabled.isChecked();
Vec3d mirrorPos = new Vec3d(0, 64, 0);
try {
mirrorPos = new Vec3d(textMirrorPosX.getNumber(), textMirrorPosY.getNumber(), textMirrorPosZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror position not valid.");
}
boolean mirrorX = buttonMirrorX.isChecked();
boolean mirrorY = buttonMirrorY.isChecked();
boolean mirrorZ = buttonMirrorZ.isChecked();
int mirrorRadius = 50;
try {
mirrorRadius = (int) textMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not valid.");
}
Mirror.MirrorSettings m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes);
//ARRAY
boolean arrayEnabled = buttonArrayEnabled.isChecked();
BlockPos arrayOffset = new BlockPos(0, 0, 0);
try {
arrayOffset = new BlockPos(textArrayOffsetX.getNumber(), textArrayOffsetY.getNumber(), textArrayOffsetZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array offset not valid.");
}
int arrayCount = 5;
try {
arrayCount = (int) textArrayCount.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array count not valid.");
}
Array.ArraySettings a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (buildSettings == null) buildSettings = new BuildSettingsManager.BuildSettings(); if (buildSettings == null) buildSettings = new BuildSettingsManager.BuildSettings();
@@ -397,21 +126,4 @@ public class SettingsGui extends GuiScreen {
EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings));
} }
private int getArrayReach() {
try
{
//find largest offset
double x = Math.abs(textArrayOffsetX.getNumber());
double y = Math.abs(textArrayOffsetY.getNumber());
double z = Math.abs(textArrayOffsetZ.getNumber());
double largestOffset = Math.max(Math.max(x, y), z);
return (int) (largestOffset * textArrayCount.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
return -1;
}
}
private boolean isCurrentReachValid(int currentReach, int maxReach) {
return currentReach <= maxReach && currentReach > -1;
}
} }

View File

@@ -1,24 +1,42 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import com.google.common.collect.Maps;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool; import net.minecraft.item.ItemTool;
import net.minecraft.util.math.*; import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorldEventListener;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.*; import nl.requios.effortlessbuilding.*;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.Color; import org.lwjgl.util.Color;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Mod.EventBusSubscriber(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT)
public class RenderHelper { public class RenderHelper implements IWorldEventListener {
private static final Color colorX = new Color(255, 72, 52); private static final Color colorX = new Color(255, 72, 52);
private static final Color colorY = new Color(67, 204, 51); private static final Color colorY = new Color(67, 204, 51);
@@ -27,15 +45,23 @@ public class RenderHelper {
private static final int planeAlpha = 75; private static final int planeAlpha = 75;
private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
public static void begin(float partialTicks) { private static List<BlockPos> previousCoordinates;
private static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getMinecraft().player; EntityPlayer player = Minecraft.getMinecraft().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks; double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks; double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks; double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ); Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glPushMatrix(); GL11.glPushMatrix();
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glDepthMask(false);
}
private static void beginLines() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_CULL_FACE); GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_TEXTURE_2D);
@@ -43,16 +69,42 @@ public class RenderHelper {
GL11.glEnable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glLineWidth(2); GL11.glLineWidth(2);
GL11.glDepthMask(false);
} }
public static void end() { private static void endLines() {
GL11.glPopAttrib();
}
private static void beginBlockPreviews() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_TEXTURE_2D);
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_CONSTANT_ALPHA, GL11.GL_ONE_MINUS_CONSTANT_ALPHA);
GL14.glBlendColor(1F, 1F, 1F, 0.8f);
}
private static void endBlockPreviews() {
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.disableBlend();
GL11.glPopAttrib();
}
private static void end() {
GL11.glDepthMask(true); GL11.glDepthMask(true);
GL11.glPopMatrix(); GL11.glPopMatrix();
GL11.glPopAttrib(); }
private static void renderBlockPreview(BlockRendererDispatcher dispatcher, BlockPos blockPos, IBlockState blockState) {
GlStateManager.pushMatrix();
GlStateManager.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ());
GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F);
GlStateManager.translate(-0.005f, -0.005f, 0.005f);
GlStateManager.scale(1.01f, 1.01f, 1.01f);
dispatcher.renderBlockBrightness(blockState, 0.85f);
GlStateManager.popMatrix();
} }
public static void renderBlockOutline(BlockPos pos) { public static void renderBlockOutline(BlockPos pos) {
@@ -65,20 +117,19 @@ public class RenderHelper {
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026); AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
RenderGlobal.drawSelectionBoundingBox(aabb, 1f, 1f, 1f, 0.6f); RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f);
} }
@SubscribeEvent @SubscribeEvent
public static void onRender(RenderWorldLastEvent event) { public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player; EntityPlayer player = Minecraft.getMinecraft().player;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
if (buildSettings == null) return;
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
Array.ArraySettings a = buildSettings.getArraySettings();
begin(event.getPartialTicks()); begin(event.getPartialTicks());
//Mirror //Mirror lines and areas
beginLines();
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ)) if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ))
{ {
Vec3d pos = m.position.add(epsilon); Vec3d pos = m.position.add(epsilon);
@@ -112,53 +163,81 @@ public class RenderHelper {
{ {
drawMirrorLines(m); drawMirrorLines(m);
} }
} }
endLines();
//Render block outlines //Render block previews
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) if (objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK)
{ {
BlockPos blockPos = objectMouseOver.getBlockPos(); beginBlockPreviews();
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
BlockPos startPos = objectMouseOver.getBlockPos();
//Check if tool (or none) in hand //Check if tool (or none) in hand
ItemStack mainhand = player.getHeldItemMainhand(); ItemStack mainhand = player.getHeldItemMainhand();
//ItemStack offhand = player.getHeldItemOffhand(); boolean toolInHand = mainhand.isEmpty() || (!mainhand.isEmpty() && mainhand.getItem() instanceof ItemTool);
//boolean noneInHand = mainhand.isEmpty() && (offhand.isEmpty() || offhand.getItem() instanceof ItemTool); boolean replaceable =
boolean toolInHand = !mainhand.isEmpty() && mainhand.getItem() instanceof ItemTool; player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!buildSettings.doQuickReplace() && !toolInHand) { if (!buildSettings.doQuickReplace() && !toolInHand && !replaceable) {
blockPos = blockPos.offset(objectMouseOver.sideHit); startPos = startPos.offset(objectMouseOver.sideHit);
} }
if (buildSettings.doQuickReplace() && !toolInHand) {
//Get under tall grass and other replaceable blocks //Get under tall grass and other replaceable blocks
if (player.world.getBlockState(blockPos).getBlock().isReplaceable(player.world, blockPos)) { if (buildSettings.doQuickReplace() && !toolInHand && replaceable) {
blockPos = blockPos.down(); startPos = startPos.down();
}
} }
//Render current block outline based on config, or when QuickReplace is enabled //get coordinates
if (buildSettings.doQuickReplace() || BuildConfig.visuals.showOutlineOnCurrentBlock) { List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startPos);
RenderHelper.renderBlockOutline(blockPos);
if (BuildModifiers.isEnabled(buildSettings, startPos) || BuildConfig.visuals.alwaysShowBlockPreview) {
//check if they are different from previous
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates;
//if so, renew randomness of randomizer bag
ItemRandomizerBag.renewRandomness();
} }
//Mirror Vec3d hitVec = objectMouseOver.hitVec;
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ) && hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
!(blockPos.getX() + 0.5 < m.position.x - m.radius) && !(blockPos.getX() + 0.5 > m.position.x + m.radius) && Math.abs(hitVec.z - ((int) hitVec.z)));
!(blockPos.getY() + 0.5 < m.position.y - m.radius) && !(blockPos.getY() + 0.5 > m.position.y + m.radius) && List<ItemStack> itemStacks = new ArrayList<>();
!(blockPos.getZ() + 0.5 < m.position.z - m.radius) && !(blockPos.getZ() + 0.5 > m.position.z + m.radius)) List<IBlockState> blockStates = BuildModifiers.findBlockStates(player, startPos, hitVec, objectMouseOver.sideHit, itemStacks);
{
if (m.mirrorX) drawMirrorBlockOutlineX(buildSettings, blockPos);
if (m.mirrorY) drawMirrorBlockOutlineY(buildSettings, blockPos);
if (m.mirrorZ) drawMirrorBlockOutlineZ(buildSettings, blockPos);
}
//Array //check if valid blockstates
if (a != null && a.enabled && (a.offset.getX() != 0 || a.offset.getY() != 0 || a.offset.getZ() != 0)) { if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
drawArrayBlockOutlines(a, blockPos); for (int i = newCoordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = newCoordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.get(i);
//Check if can place
if (!itemstack.isEmpty() && SurvivalHelper.canPlayerEdit(player, player.world, blockPos, itemstack) &&
SurvivalHelper.mayPlace(player.world, Block.getBlockFromItem(itemstack.getItem()), blockState, blockPos, true, EnumFacing.UP, player) &&
SurvivalHelper.canReplace(player.world, player, blockPos)) {
renderBlockPreview(dispatcher, blockPos, blockState);
} }
} }
}
}
endBlockPreviews();
beginLines();
//Draw outlines if tool in hand
if (toolInHand) {
for (int i = 1; i < newCoordinates.size(); i++) {
BlockPos coordinate = newCoordinates.get(i);
IBlockState blockState = player.world.getBlockState(coordinate);
if (!blockState.getBlock().isAir(blockState, player.world, coordinate) &&
SurvivalHelper.canBreak(player.world, player, coordinate)) {
renderBlockOutline(coordinate);
}
}
}
endLines();
}
end(); end();
} }
@@ -247,61 +326,82 @@ public class RenderHelper {
tessellator.draw(); tessellator.draw();
} }
public static void drawMirrorBlockOutlineX(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) { //IWORLDEVENTLISTENER IMPLEMENTATION
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); @Override
//find mirror position public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
RenderHelper.renderBlockOutline(newBlockPos);
//Array synergy
drawArrayBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
if (m.mirrorY) drawMirrorBlockOutlineY(buildSettings, newBlockPos);
if (m.mirrorZ) drawMirrorBlockOutlineZ(buildSettings, newBlockPos);
}
public static void drawMirrorBlockOutlineY(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
RenderHelper.renderBlockOutline(newBlockPos);
//Array synergy
drawArrayBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
if (m.mirrorZ) drawMirrorBlockOutlineZ(buildSettings, newBlockPos);
}
public static void drawMirrorBlockOutlineZ(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
RenderHelper.renderBlockOutline(newBlockPos);
//Array synergy
drawArrayBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
}
//----Array----
public static void drawArrayBlockOutlines(Array.ArraySettings a, BlockPos pos) {
if (a == null || !a.enabled || (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0)) return;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
//RenderHelper.renderBlockOutline(blockPos);
for (int i = 0; i < a.count; i++)
{
pos = pos.add(offset);
RenderHelper.renderBlockOutline(pos);
}
}
} }
@Override
public void notifyLightSet(BlockPos pos) {
}
@Override
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
}
@Override
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category,
double x, double y, double z, float volume, float pitch) {
}
@Override
public void playRecord(SoundEvent soundIn, BlockPos pos) {
}
@Override
public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord,
double xSpeed, double ySpeed, double zSpeed, int... parameters) {
}
@Override
public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z,
double xSpeed, double ySpeed, double zSpeed, int... parameters) {
}
@Override
public void onEntityAdded(Entity entityIn) {
}
@Override
public void onEntityRemoved(Entity entityIn) {
}
@Override
public void broadcastSound(int soundID, BlockPos pos, int data) {
}
@Override
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) {
}
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
Minecraft mc = Minecraft.getMinecraft();
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (!BuildModifiers.isEnabled(buildSettings, pos)) return;
List<BlockPos> coordinates = BuildModifiers.findCoordinates(mc.player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) {
//Send i as entity id because only one block can be broken per id
//Unless i happens to be the player id, then take something else
int fakeId = mc.player.getEntityId() != i ? i : coordinates.size();
mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress);
}
}
}
}

View File

@@ -1,6 +1,7 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
@@ -20,6 +21,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
@@ -108,11 +110,12 @@ public class SurvivalHelper {
//Can break using held tool? (or in creative) //Can break using held tool? (or in creative)
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) { public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
IBlockState blockState = world.getBlockState(pos);
if (blockState.getBlock() instanceof BlockLiquid) return false;
if (player.isCreative()) return true; if (player.isCreative()) return true;
IBlockState blockState = world.getBlockState(pos);
return canHarvestBlock(blockState.getBlock(), player, world, pos); return canHarvestBlock(blockState.getBlock(), player, world, pos);
} }
//From ForgeHooks#canHarvestBlock //From ForgeHooks#canHarvestBlock
@@ -169,21 +172,23 @@ public class SurvivalHelper {
} }
//From EntityPlayer#canPlayerEdit //From EntityPlayer#canPlayerEdit
private static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack) public static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack)
{ {
if (player.capabilities.allowEdit) if (player.capabilities.allowEdit)
{ {
//True in creative and survival mode
return true; return true;
} }
else else
{ {
//Adventure mode
Block block = world.getBlockState(pos).getBlock(); Block block = world.getBlockState(pos).getBlock();
return stack.canPlaceOn(block) || stack.canEditBlocks(); return stack.canPlaceOn(block) || stack.canEditBlocks();
} }
} }
//From World#mayPlace //From World#mayPlace
private static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer) public static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
{ {
IBlockState iblockstate1 = world.getBlockState(pos); IBlockState iblockstate1 = world.getBlockState(pos);
AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(world, pos); AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(world, pos);
@@ -204,9 +209,11 @@ public class SurvivalHelper {
return true; return true;
} }
//TODO check config for allow to replace //Check quickreplace
if (placer instanceof EntityPlayer && BuildSettingsManager.getBuildSettings(((EntityPlayer) placer)).doQuickReplace()) {
return true; return true;
//TODO fix check canPlaceBlockOnSide }
//return /*iblockstate1.getBlock().isReplaceable(world, pos) &&*/ blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
} }
} }

View File

@@ -24,13 +24,15 @@ import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
public class ItemRandomizerBag extends Item { public class ItemRandomizerBag extends Item {
public static final int INV_SIZE = 5; public static final int INV_SIZE = 5;
private static Random rand = new Random(1337); private static long currentSeed = 1337;
private static Random rand = new Random(currentSeed);
public ItemRandomizerBag() { public ItemRandomizerBag() {
this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag"); this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag");
@@ -182,4 +184,13 @@ public class ItemRandomizerBag extends Item {
public String getUnlocalizedName() { public String getUnlocalizedName() {
return super.getUnlocalizedName(); return super.getUnlocalizedName();
} }
public static void resetRandomness() {
rand.setSeed(currentSeed);
}
public static void renewRandomness() {
currentSeed = Calendar.getInstance().getTimeInMillis();
rand.setSeed(currentSeed);
}
} }

View File

@@ -4,30 +4,34 @@ import io.netty.buffer.ByteBuf;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.BuildModifiers;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.QuickReplace;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
public class QuickReplaceMessage implements IMessage { public class BlockPlacedMessage implements IMessage {
private boolean blockHit; private boolean blockHit;
private BlockPos blockPos; private BlockPos blockPos;
private EnumFacing sideHit; private EnumFacing sideHit;
private Vec3d hitVec;
public QuickReplaceMessage() { public BlockPlacedMessage() {
this.blockHit = false; this.blockHit = false;
this.blockPos = BlockPos.ORIGIN; this.blockPos = BlockPos.ORIGIN;
this.sideHit = EnumFacing.UP; this.sideHit = EnumFacing.UP;
this.hitVec = new Vec3d(0, 0, 0);
} }
public QuickReplaceMessage(RayTraceResult result) { public BlockPlacedMessage(RayTraceResult result) {
this.blockHit = result.typeOfHit == RayTraceResult.Type.BLOCK; this.blockHit = result.typeOfHit == RayTraceResult.Type.BLOCK;
this.blockPos = result.getBlockPos(); this.blockPos = result.getBlockPos();
this.sideHit = result.sideHit; this.sideHit = result.sideHit;
this.hitVec = result.hitVec;
} }
public boolean isBlockHit() { public boolean isBlockHit() {
@@ -42,6 +46,10 @@ public class QuickReplaceMessage implements IMessage {
return sideHit; return sideHit;
} }
public Vec3d getHitVec() {
return hitVec;
}
@Override @Override
public void toBytes(ByteBuf buf) { public void toBytes(ByteBuf buf) {
buf.writeBoolean(blockHit); buf.writeBoolean(blockHit);
@@ -49,6 +57,9 @@ public class QuickReplaceMessage implements IMessage {
buf.writeInt(blockPos.getY()); buf.writeInt(blockPos.getY());
buf.writeInt(blockPos.getZ()); buf.writeInt(blockPos.getZ());
buf.writeInt(sideHit.getIndex()); buf.writeInt(sideHit.getIndex());
buf.writeDouble(hitVec.x);
buf.writeDouble(hitVec.y);
buf.writeDouble(hitVec.z);
} }
@Override @Override
@@ -56,34 +67,29 @@ public class QuickReplaceMessage implements IMessage {
blockHit = buf.readBoolean(); blockHit = buf.readBoolean();
blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
sideHit = EnumFacing.getFront(buf.readInt()); sideHit = EnumFacing.getFront(buf.readInt());
hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
} }
// The params of the IMessageHandler are <REQ, REPLY> // The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<QuickReplaceMessage, IMessage> { public static class MessageHandler implements IMessageHandler<BlockPlacedMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case // Do note that the default constructor is required, but implicitly defined in this case
@Override @Override
public IMessage onMessage(QuickReplaceMessage message, MessageContext ctx) { public IMessage onMessage(BlockPlacedMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side"); //EffortlessBuilding.log("message received on " + ctx.side + " side");
if (ctx.side == Side.CLIENT){ if (ctx.side == Side.CLIENT){
//Received clientside //Received clientside
//Send back your info //Send back your info
return new QuickReplaceMessage(ClientProxy.previousLookAt); return new BlockPlacedMessage(ClientProxy.previousLookAt);
//TODO break block then return
// Minecraft.getMinecraft().addScheduledTask(() -> {
// EffortlessBuilding.packetHandler.sendToServer(new QuickReplaceMessage(Minecraft.getMinecraft().objectMouseOver));
// });
} else { } else {
//Received serverside //Received serverside
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> { EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
QuickReplace.onMessageReceived(ctx.getServerHandler().player, message); BuildModifiers.onBlockPlacedMessage(ctx.getServerHandler().player, message);
}); });
}
// No response packet // No response packet
return null; return null;
} }
} }
} }
}

View File

@@ -2,18 +2,27 @@ package nl.requios.effortlessbuilding.proxy;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
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.item.Item; import net.minecraft.item.Item;
import net.minecraft.util.IThreadListener; import net.minecraft.util.IThreadListener;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.IWorldEventListener;
import net.minecraft.world.World;
import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.*; import net.minecraftforge.fml.common.event.*;
@@ -26,8 +35,12 @@ import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.BuildSettingsManager; import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.gui.SettingsGui; import nl.requios.effortlessbuilding.gui.SettingsGui;
import nl.requios.effortlessbuilding.helper.RenderHelper;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import scala.collection.parallel.ParIterableLike;
import javax.annotation.Nullable;
@Mod.EventBusSubscriber(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT)
public class ClientProxy implements IProxy { public class ClientProxy implements IProxy {
@@ -86,6 +99,13 @@ public class ClientProxy implements IProxy {
} }
} }
@SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getEntity() == Minecraft.getMinecraft().player) {
event.getWorld().addEventListener(new RenderHelper());
}
}
@SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true)
public static void onKeyPress(InputEvent.KeyInputEvent event) { public static void onKeyPress(InputEvent.KeyInputEvent event) {
EntityPlayerSP player = Minecraft.getMinecraft().player; EntityPlayerSP player = Minecraft.getMinecraft().player;
@@ -127,6 +147,8 @@ public class ClientProxy implements IProxy {
public static void onClientTick(TickEvent.ClientTickEvent event) { public static void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; if (event.phase != TickEvent.Phase.START) return;
//TODO increase range using getLookingAt
// Would also need other trigger than onBlockPlaced
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return; if (objectMouseOver == null) return;
@@ -148,7 +170,14 @@ public class ClientProxy implements IProxy {
} }
} }
} }
}
private static float rayTraceRange = 32f;
public static RayTraceResult getLookingAt(EntityPlayer player) {
World world = player.world;
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
Vec3d end = new Vec3d(player.posX + look.x * rayTraceRange, player.posY + player.getEyeHeight() + look.y * rayTraceRange, player.posZ + look.z * rayTraceRange);
return world.rayTraceBlocks(start, end, false, false, false);
} }
} }

View File

@@ -1,6 +1,5 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.client.entity.AbstractClientPlayer;
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.util.IThreadListener; import net.minecraft.util.IThreadListener;
@@ -9,10 +8,6 @@ import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent; import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.network.QuickReplaceMessage;
public class ServerProxy implements IProxy public class ServerProxy implements IProxy
{ {