11 Commits
0.3 ... 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
Christian Knaapen
1933832c58 Fixed rare crash on ladders.
Added config file with reach, increased mining time and block outline settings.
Mirror size has been renamed to reach.
Mirror and array abide by the new reach settings.
Added reach counter to array UI (reach = count * max offset).
If reach is 0 (as can be set in config), the UI will be disabled.
Added the ability to show the white block outline on the block you place, in addition to blocks placed by mirror/array.
Added the ability to disable increased mining time and to change its percentage in the config.
2018-12-01 18:33:21 +01:00
Christian Knaapen
3891cc349f Mining speed is decreased based on blocks mined (extra blocks count for 50%, which will be configurable).
Tool durability is checked after each block break (no more breaking 5 blocks with 1 durability).
Fortune is taken into account.
Outlines now change to blocks that will be broken when holding tools.
Added indication QuickReplace is on: outline of current block will be white.
Fixed opening Randomizer Bag in offhand.
Fixed placing blocks with Randomizer Bag in offhand.
Fixed mirror block outline showing up outside range.
Fixed outline of QuickReplace not being under replaceables like tall grass.
2018-11-04 18:43:16 +01:00
Christian Knaapen
2ea44f22b5 GUI overhaul. Added +- buttons with shift/ctrl clicking. Rightclick to clear. Tooltips. Scroll to change number.
See empty fields as 0 instead of reset. Images for buttons. Added Toggle 0.5 button.
Can now click "mirror/array enabled" label to toggle.
2018-10-28 19:38:44 +01:00
Christian Knaapen
e2e48a4451 Fixed shiftclicking items into a Randomizer Bag when it is almost full. 2018-10-27 16:04:42 +02:00
Christian Knaapen
c2e29419ca Moved all rendering code to RenderHelper to resolve #3 Crash on stand alone server startup.
Made sure getBuildSettings never returns null to resolve #4 Client Crash W/ OpenBlocks.
Now compatible with block placers and breakers from OpenBlocks (even the Randomizer Bag works in the placer).
Fixed the breakEvent in mirror for array synergy to use the blockstate of the new position. Resolves #5 Crash after destorying blocks with hand.
2018-10-27 14:20:00 +02:00
Christian Knaapen
bb359113f2 Version update and cleanup 2018-10-21 17:05:05 +02:00
34 changed files with 2476 additions and 946 deletions

BIN
Logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

BIN
Logo.xcf

Binary file not shown.

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.2" 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

@@ -2,28 +2,24 @@ package nl.requios.effortlessbuilding;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
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.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.RayTraceResult; 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.client.event.RenderWorldLastEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
@Mod.EventBusSubscriber import java.util.ArrayList;
import java.util.List;
public class Array { public class Array {
//TODO config file
public static final int MAX_COUNT = 100;
public static class ArraySettings{ public static class ArraySettings{
public boolean enabled = false; public boolean enabled = false;
@@ -38,113 +34,75 @@ public class Array {
this.offset = offset; this.offset = offset;
this.count = count; this.count = count;
} }
public int getReach() {
//find largest offset
int x = Math.abs(offset.getX());
int y = Math.abs(offset.getY());
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
return largestOffset * count;
}
} }
//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
ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates;
BlockPos pos = startPos;
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);
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 //find arraysettings for the player that placed the block
ArraySettings a = BuildSettingsManager.getBuildSettings(event.getPlayer()).getArraySettings(); ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (a == null || !a.enabled) return false; if (!isEnabled(a)) return blockStates;
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());
//Randomizer bag synergy //Randomizer bag synergy
IItemHandler bagInventory = null; IItemHandler bagInventory = null;
if (event.getPlayer().getHeldItemMainhand().getItem() instanceof ItemRandomizerBag) { if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(event.getPlayer().getHeldItemMainhand()); bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
} }
//Get itemstack
ItemStack itemStack = event.getPlayer().getHeldItem(event.getHand());
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);
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) {
//TODO get facing from getPlacedAgainst and getPlacedBlock
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(world, pos, EnumFacing.NORTH, 0, 0, 0, itemStack.getMetadata(), player, EnumHand.MAIN_HAND);
}
//Called from EventHandler
public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote) return;
//find arraysettings for the player that placed 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);
}
}
@SubscribeEvent
@SideOnly(Side.CLIENT)
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
if (buildSettings == null) return;
ArraySettings a = buildSettings.getArraySettings();
if (a == null || !a.enabled || (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0)) return;
RenderHelper.begin(event.getPartialTicks());
//Render block outlines
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK)
{
BlockPos blockPos = objectMouseOver.getBlockPos();
if (!buildSettings.doQuickReplace()) blockPos = blockPos.offset(objectMouseOver.sideHit);
drawBlockOutlines(a, blockPos);
}
RenderHelper.end();
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlines(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);
}
}
} }

View File

@@ -0,0 +1,54 @@
package nl.requios.effortlessbuilding;
import net.minecraftforge.common.config.Config;
import static net.minecraftforge.common.config.Config.*;
@Config(modid = EffortlessBuilding.MODID, name = "EffortlessBuilding", type = Type.INSTANCE, category = "")
public class BuildConfig {
public static Reach reach = new Reach();
public static SurvivalBalancers survivalBalancers = new SurvivalBalancers();
public static Visuals visuals = new Visuals();
public static class Reach {
@Comment({"Reach: how far away the player can place blocks using mirror/array etc.",
"Maximum reach in creative"})
public int maxReachCreative = 200;
@Comment({"Maximum reach in survival without upgrades",
"Reach upgrades are craftable consumables that permanently increase reach.",
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade."})
public int maxReachLevel0 = 20;
@Comment("Maximum reach in survival with one upgrade")
public int maxReachLevel1 = 50;
@Comment("Maximum reach in survival with two upgrades")
public int maxReachLevel2 = 100;
@Comment("Maximum reach in survival with three upgrades")
public int maxReachLevel3 = 200;
}
public static class SurvivalBalancers {
@Comment({"Increases the time to mine a block when breaking multiple at once.",
"Mining time depends on how many blocks, what type of blocks, and the percentage below.",
"Example: breaking 1 dirt + 1 obsidian takes the time of breaking 1 dirt + 1 obsidian."})
public boolean increasedMiningTime = true;
@Comment({"How much the mining time of each additional block counts towards an increased mining time.",
"A percentage between 0% and 100%, where 0% is the same as disabling it,",
"and 100% takes as much time as breaking each block individually.",
"The block in front of you always counts as 100%."})
@RangeInt(min = 0, max = 100)
public int miningTimePercentage = 50;
}
public static class Visuals {
@Comment({"Show a block preview if you have a block in hand,",
"even when mirror and array are off."})
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

@@ -5,48 +5,108 @@ import net.minecraft.entity.player.EntityPlayerMP;
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 buildModifierCapability capability
//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) {
capability.setBuildModifierData(new BuildSettings());
}
return capability.getBuildModifierData(); return capability.getBuildModifierData();
} }
EffortlessBuilding.log("buildsettings is null"); throw new IllegalArgumentException("Player does not have buildModifierCapability capability");
return null;
} }
public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) { public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) {
if (player == null) { if (player == null) {
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.");
} }
} }
public static String sanitize(BuildSettings buildSettings, EntityPlayer player) {
int maxReach = getMaxReach(player);
String error = "";
//Mirror settings
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m.radius < 1) {
m.radius = 1;
error += "Mirror size is too small. Size has been set to 1. ";
}
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach. Reach has been set to max. ";
}
//Array settings
Array.ArraySettings a = buildSettings.getArraySettings();
if (a.count < 0) {
a.count = 0;
error += "Array count cannot be negative. Count has been set to 0. ";
}
if (a.getReach() > maxReach) {
a.count = 0;
error += "Array exceeds your maximum reach. Count has been set to 0. ";
}
//Other
if (buildSettings.reachUpgrade < 0) {
buildSettings.reachUpgrade = 0;
}
if (buildSettings.reachUpgrade > 3) {
buildSettings.reachUpgrade = 3;
}
return error;
}
public static int getMaxReach(EntityPlayer player) {
if (player.isCreative()) return BuildConfig.reach.maxReachCreative;
//Check buildsettings for reachUpgrade
int reachUpgrade = getBuildSettings(player).getReachUpgrade();
switch (reachUpgrade) {
case 0: return BuildConfig.reach.maxReachLevel0;
case 1: return BuildConfig.reach.maxReachLevel1;
case 2: return BuildConfig.reach.maxReachLevel2;
case 3: return BuildConfig.reach.maxReachLevel3;
}
return BuildConfig.reach.maxReachLevel0;
}
public static class BuildSettings { public static class BuildSettings {
private Mirror.MirrorSettings mirrorSettings; private Mirror.MirrorSettings mirrorSettings;
private Array.ArraySettings arraySettings; private Array.ArraySettings arraySettings;
private boolean quickReplace = false; private boolean quickReplace = false;
private int reachUpgrade = 0;
public BuildSettings() { public BuildSettings() {
mirrorSettings = new Mirror.MirrorSettings(); mirrorSettings = new Mirror.MirrorSettings();
arraySettings = new Array.ArraySettings(); arraySettings = new Array.ArraySettings();
} }
public BuildSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings, boolean quickReplace) { public BuildSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings, boolean quickReplace, int reachUpgrade) {
this.mirrorSettings = mirrorSettings; this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings; this.arraySettings = arraySettings;
this.quickReplace = quickReplace; this.quickReplace = quickReplace;
this.reachUpgrade = reachUpgrade;
} }
public Mirror.MirrorSettings getMirrorSettings() { public Mirror.MirrorSettings getMirrorSettings() {
@@ -72,6 +132,14 @@ public class BuildSettingsManager {
public void setQuickReplace(boolean quickReplace) { public void setQuickReplace(boolean quickReplace) {
this.quickReplace = quickReplace; this.quickReplace = quickReplace;
} }
public int getReachUpgrade() {
return reachUpgrade;
}
public void setReachUpgrade(int reachUpgrade) {
this.reachUpgrade = reachUpgrade;
}
} }
@SubscribeEvent @SubscribeEvent

View File

@@ -5,6 +5,8 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.SidedProxy;
@@ -19,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;
@@ -29,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.2"; public static final String VERSION = "0.5";
@Mod.Instance(EffortlessBuilding.MODID) @Mod.Instance(EffortlessBuilding.MODID)
public static EffortlessBuilding instance; public static EffortlessBuilding instance;
@@ -61,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);
} }
@@ -77,6 +80,7 @@ public class EffortlessBuilding
// Register network handlers // Register network handlers
public void init(FMLInitializationEvent event) public void init(FMLInitializationEvent event)
{ {
ConfigManager.sync(MODID, Config.Type.INSTANCE);
NetworkRegistry.INSTANCE.registerGuiHandler(EffortlessBuilding.instance, new RandomizerBagGuiHandler()); NetworkRegistry.INSTANCE.registerGuiHandler(EffortlessBuilding.instance, new RandomizerBagGuiHandler());
proxy.init(event); proxy.init(event);
} }

View File

@@ -7,24 +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.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.config.Config;
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.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.BlockEvent;
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)
@@ -46,37 +52,67 @@ 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());
} }
} }
@SubscribeEvent @SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent event) { public void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event)
if (placedBlock) { {
placedBlock = false; if (event.getModID().equals(EffortlessBuilding.MODID))
{
ConfigManager.sync(EffortlessBuilding.MODID, Config.Type.INSTANCE);
}
}
Mirror.onBlockPlaced(placeEvent); // @SubscribeEvent
Array.onBlockPlaced(placeEvent); // public static void onServerTick(TickEvent.ServerTickEvent event) {
} //
} // }
@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
public static void breakSpeed(PlayerEvent.BreakSpeed event) {
//Disable if config says so
if (!BuildConfig.survivalBalancers.increasedMiningTime) return;
EntityPlayer player = event.getEntityPlayer();
World world = player.world;
BlockPos pos = event.getPos();
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
float originalBlockHardness = event.getState().getBlockHardness(world, pos);
float totalBlockHardness = 0;
//get coordinates
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
float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage / 100;
totalBlockHardness *= percentage;
totalBlockHardness += originalBlockHardness;
float newSpeed = event.getOriginalSpeed() / totalBlockHardness * originalBlockHardness;
if (Float.isNaN(newSpeed) || newSpeed == 0f) newSpeed = 1f;
event.setNewSpeed(newSpeed);
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
}
} }

View File

@@ -2,51 +2,31 @@ package nl.requios.effortlessbuilding;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
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.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.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.Color;
@Mod.EventBusSubscriber import java.util.ArrayList;
import java.util.List;
public class Mirror { public class Mirror {
//TODO config file
public static final int MAX_RADIUS = 200;
private static final Color colorX = new Color(255, 72, 52);
private static final Color colorY = new Color(67, 204, 51);
private static final Color colorZ = new Color(52, 247, 255);
private static final int lineAlpha = 200;
private static final int planeAlpha = 75;
private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
public static class MirrorSettings { public static class MirrorSettings {
public boolean enabled = false; public boolean enabled = false;
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() {
} }
@@ -61,50 +41,74 @@ public class Mirror {
this.drawLines = drawLines; this.drawLines = drawLines;
this.drawPlanes = drawPlanes; this.drawPlanes = drawPlanes;
} }
public int getReach() {
return radius * 2;
}
} }
//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);
ItemStack itemStack = event.getPlayer().getHeldItem(event.getHand()); if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates);
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;
if (event.getPlayer().getHeldItem(event.getHand()).getItem() == EffortlessBuilding.ITEM_RANDOMIZER_BAG) { if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(event.getPlayer().getHeldItem(EnumHand.MAIN_HAND)); 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); 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); 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);
}
return true;
}
private static void placeMirrorX(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState, IItemHandler bagInventory, ItemStack itemStack) {
//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());
@@ -112,21 +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);
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); //Store blockstate and itemstack
} blockStates.add(newBlockState);
if (m.mirrorY) placeMirrorY(world, player, m, newBlockPos, newBlockState, bagInventory, itemStack); itemStacks.add(itemStack);
if (m.mirrorZ) placeMirrorZ(world, player, m, newBlockPos, newBlockState, bagInventory, itemStack);
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, IItemHandler bagInventory, ItemStack itemStack) { private static void blockStateMirrorY(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
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());
@@ -134,20 +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);
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); //Store blockstate and itemstack
} blockStates.add(newBlockState);
if (m.mirrorZ) placeMirrorZ(world, player, m, newBlockPos, newBlockState, bagInventory, itemStack); 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, IItemHandler bagInventory, ItemStack itemStack) { private static void blockStateMirrorZ(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
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);
@@ -155,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);
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); //Store blockstate and itemstack
} blockStates.add(newBlockState);
itemStacks.add(itemStack);
} }
private static IBlockState getBlockStateFromRandomizerBag(IItemHandler bagInventory, World world, EntityPlayer player, BlockPos pos, ItemStack itemStack) { 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, EnumHand.MAIN_HAND);
}
private static void placeBlock(World world, EntityPlayer player, BlockPos newBlockPos, IBlockState newBlockState, ItemStack itemStack) { //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, EnumHand.MAIN_HAND);
Array.onBlockPlaced(placeEvent);
} }
private static IBlockState getVerticalMirror(IBlockState blockState) { private static IBlockState getVerticalMirror(IBlockState blockState) {
@@ -224,257 +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.getState(), event.getPlayer());
Array.onBlockBroken(breakEvent);
}
@SubscribeEvent
@SideOnly(Side.CLIENT)
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
if (buildSettings == null) return;
MirrorSettings m = buildSettings.getMirrorSettings();
if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return;
RenderHelper.begin(event.getPartialTicks());
Vec3d pos = m.position.add(epsilon);
int radius = m.radius;
if (m.mirrorX) {
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes);
}
if (m.mirrorY) {
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ) {
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes);
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) {
drawMirrorLines(m);
}
//Render block outlines
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK)
{
BlockPos blockPos = objectMouseOver.getBlockPos();
if (!buildSettings.doQuickReplace()) blockPos = blockPos.offset(objectMouseOver.sideHit);
//RenderHelper.renderBlockOutline(blockPos);
if (m.mirrorX) drawBlockOutlineX(buildSettings, blockPos);
if (m.mirrorY) drawBlockOutlineY(buildSettings, blockPos);
if (m.mirrorZ) drawBlockOutlineZ(buildSettings, blockPos);
}
RenderHelper.end();
}
@SideOnly(Side.CLIENT)
public static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
@SideOnly(Side.CLIENT)
public static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
@SideOnly(Side.CLIENT)
public static void drawMirrorLines(MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
GL11.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlineX(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
MirrorSettings m = buildSettings.getMirrorSettings();
//find mirror position
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
Array.drawBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
if (m.mirrorY) drawBlockOutlineY(buildSettings, newBlockPos);
if (m.mirrorZ) drawBlockOutlineZ(buildSettings, newBlockPos);
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlineY(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
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
Array.drawBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
if (m.mirrorZ) drawBlockOutlineZ(buildSettings, newBlockPos);
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlineZ(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
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
Array.drawBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
}
} }

View File

@@ -1,71 +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.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<>();
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()));
//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;
//TODO check for bedrock, end portal etc in survival
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());
SurvivalHelper.placeBlock(player.world, player, placedAgainstBlockPos, blockState, itemStack, message.getSideHit(), true, false);
//Mirror and Array synergy
BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, placedAgainstBlockPos, blockState);
BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, EnumHand.MAIN_HAND);
Mirror.onBlockPlaced(placeEvent);
Array.onBlockPlaced(placeEvent);
}
}

View File

@@ -1,60 +0,0 @@
package nl.requios.effortlessbuilding;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.Color;
@SideOnly(Side.CLIENT)
public class RenderHelper {
public static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getMinecraft().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glLineWidth(2);
GL11.glDepthMask(false);
}
public static void end() {
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
public static void renderBlockOutline(BlockPos pos) {
renderBlockOutline(pos, pos);
}
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
public static void renderBlockOutline(BlockPos pos1, BlockPos pos2) {
GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
RenderGlobal.drawSelectionBoundingBox(aabb, 1f, 1f, 1f, 0.6f);
}
}

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,11 +44,12 @@ 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();
//MIRROR //MIRROR
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
@@ -71,12 +72,14 @@ public class BuildModifierCapability {
compound.setInteger("arrayOffsetZ", a.offset.getZ()); compound.setInteger("arrayOffsetZ", a.offset.getZ());
compound.setInteger("arrayCount", a.count); compound.setInteger("arrayCount", a.count);
compound.setInteger("reachUpgrade", buildSettings.getReachUpgrade());
//compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace //compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
return compound; return compound;
} }
@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
@@ -96,43 +99,45 @@ public class BuildModifierCapability {
int arrayCount = compound.getInteger("arrayCount"); int arrayCount = compound.getInteger("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
int reachUpgrade = compound.getInteger("reachUpgrade");
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace //boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
BuildSettings buildSettings = new BuildSettings(mirrorSettings, arraySettings, false); BuildSettings buildSettings = new BuildSettings(mirrorSettings, arraySettings, false, reachUpgrade);
instance.setBuildModifierData(buildSettings); instance.setBuildModifierData(buildSettings);
} }
} }
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

@@ -0,0 +1,75 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class GuiIconButton extends GuiButton {
private final ResourceLocation resourceLocation;
private final int iconX, iconY, iconWidth, iconHeight, iconAltX, iconAltY;
List<String> tooltip = new ArrayList<>();
private boolean useAltIcon = false;
public GuiIconButton(int buttonId, int x, int y, int iconX, int iconY, ResourceLocation resourceLocation) {
this(buttonId, x, y, 20, 20, iconX, iconY, 20, 20, 20, 0, resourceLocation);
}
public GuiIconButton(int buttonId, int x, int y, int width, int height, int iconX, int iconY, int iconWidth, int iconHeight, int iconAltX, int iconAltY, ResourceLocation resourceLocation) {
super(buttonId, x, y, width, height, "");
this.iconX = iconX;
this.iconY = iconY;
this.iconWidth = iconWidth;
this.iconHeight = iconHeight;
this.iconAltX = iconAltX;
this.iconAltY = iconAltY;
this.resourceLocation = resourceLocation;
}
public void setTooltip(String tooltip) {
setTooltip(Arrays.asList(tooltip));
}
public void setTooltip(List<String> tooltip) {
this.tooltip = tooltip;
}
public void setUseAlternateIcon(boolean useAlternateIcon) {
this.useAltIcon = useAlternateIcon;
}
@Override
public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
super.drawButton(mc, mouseX, mouseY, partialTicks);
if (this.visible)
{
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
mc.getTextureManager().bindTexture(this.resourceLocation);
int currentIconX = this.iconX;
int currentIconY = this.iconY;
if (useAltIcon)
{
currentIconX += iconAltX;
currentIconY += iconAltY;
}
this.drawTexturedModalRect(this.x, this.y, currentIconX, currentIconY, this.iconWidth, this.iconHeight);
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
boolean flag = mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height;
if (flag) {
List<String> textLines = new ArrayList<>();
textLines.addAll(tooltip);
guiScreen.drawHoveringText(textLines, mouseX - 10, mouseY + 25);
}
}
}

View File

@@ -0,0 +1,154 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.util.text.TextFormatting;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class GuiNumberField extends Gui {
int x, y, width, height;
int buttonWidth = 10;
protected GuiTextField textField;
protected GuiButton minusButton, plusButton;
List<String> tooltip = new ArrayList<>();
public GuiNumberField(int id1, int id2, int id3, FontRenderer fontRenderer,
List<GuiButton> buttonList, int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
textField = new GuiTextField(id1, fontRenderer, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2);
minusButton = new GuiButton(id2, x, y - 1, buttonWidth, height + 2, "-");
plusButton = new GuiButton(id3, x + width - buttonWidth, y - 1, buttonWidth, height + 2, "+");
buttonList.add(minusButton);
buttonList.add(plusButton);
}
public void setNumber(double number) {
DecimalFormat format = new DecimalFormat("0.#");
textField.setText(format.format(number));
}
public double getNumber() {
if (textField.getText().isEmpty()) return 0;
return Double.parseDouble(textField.getText());
}
public void setTooltip(String tooltip) {
setTooltip(Arrays.asList(tooltip));
}
public void setTooltip(List<String> tooltip) {
this.tooltip = tooltip;
}
public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) {
boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton);
//Check if clicked inside textfield
boolean flag = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
//Rightclicked inside textfield
if (flag && mouseButton == 1) {
textField.setText("");
textField.setFocused(true);
result = true;
}
return result;
}
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();
minusButton.drawButton(mc, mouseX, mouseY, partialTicks);
plusButton.drawButton(mc, mouseX, mouseY, partialTicks);
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
boolean insideMinusButton = mouseX >= x && mouseX < x + buttonWidth && mouseY >= y && mouseY < y + height;
boolean insidePlusButton = mouseX >= x + width - buttonWidth && mouseX < x + width && mouseY >= y && mouseY < y + height;
List<String> textLines = new ArrayList<>();
if (insideTextField) {
if (!tooltip.isEmpty())
textLines.addAll(tooltip);
// textLines.add(TextFormatting.GRAY + "Tip: try scrolling.");
}
if (insideMinusButton) {
textLines.add("Hold " + TextFormatting.AQUA + "shift " + TextFormatting.RESET + "for " + TextFormatting.RED + "10");
textLines.add("Hold " + TextFormatting.AQUA + "ctrl " + TextFormatting.RESET + "for " + TextFormatting.RED + "5");
}
if (insidePlusButton) {
textLines.add("Hold " + TextFormatting.AQUA + "shift " + TextFormatting.RESET + "for " + TextFormatting.DARK_GREEN + "10");
textLines.add("Hold " + TextFormatting.AQUA + "ctrl " + TextFormatting.RESET + "for " + TextFormatting.DARK_GREEN + "5");
}
guiScreen.drawHoveringText(textLines, mouseX - 10, mouseY + 25);
}
protected void actionPerformed(GuiButton button) {
float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
if (button == minusButton) {
setNumber(getNumber() - valueChanged);
}
if (button == plusButton) {
setNumber(getNumber() + valueChanged);
}
}
public void update() {
textField.updateCursorCounter();
}
protected void keyTyped(char typedChar, int keyCode) throws IOException {
if (!textField.isFocused()) return;
// if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK
// || keyCode == Keyboard.KEY_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT
// || keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN) {
textField.textboxKeyTyped(typedChar, keyCode);
// }
}
//Scroll inside textfield to change number
// public void handleMouseInput(int mouseX, int mouseY) {
// boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
//
// if (insideTextField)
// {
// int valueChanged = 0;
// if (Mouse.getEventDWheel() > 0)
// valueChanged = 1;
// if (Mouse.getEventDWheel() < 0)
// valueChanged = -1;
//
// 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

@@ -46,9 +46,17 @@ public class RandomizerBagContainer extends Container {
return true; return true;
} }
@Override
public Slot getSlot(int parSlotIndex)
{
if(parSlotIndex >= inventorySlots.size())
parSlotIndex = inventorySlots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override @Override
public ItemStack transferStackInSlot(EntityPlayer playerIn, int slotIndex) { public ItemStack transferStackInSlot(EntityPlayer playerIn, int slotIndex) {
ItemStack itemstack = null; ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.inventorySlots.get(slotIndex); Slot slot = this.inventorySlots.get(slotIndex);
if (slot != null && slot.getHasStack()) { if (slot != null && slot.getHasStack()) {
@@ -59,7 +67,7 @@ public class RandomizerBagContainer extends Container {
if (slotIndex < INV_START) { if (slotIndex < INV_START) {
// try to place in player inventory / action bar // try to place in player inventory / action bar
if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true)) { if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return null; return ItemStack.EMPTY;
} }
slot.onSlotChange(itemstack1, itemstack); slot.onSlotChange(itemstack1, itemstack);
@@ -72,7 +80,7 @@ public class RandomizerBagContainer extends Container {
if (slotIndex >= INV_START) { if (slotIndex >= INV_START) {
// place in custom inventory // place in custom inventory
if (!this.mergeItemStack(itemstack1, 0, INV_START, false)) { if (!this.mergeItemStack(itemstack1, 0, INV_START, false)) {
return null; return ItemStack.EMPTY;
} }
} }
@@ -85,7 +93,7 @@ public class RandomizerBagContainer extends Container {
} }
if (itemstack1.getCount() == itemstack.getCount()) { if (itemstack1.getCount() == itemstack.getCount()) {
return null; return ItemStack.EMPTY;
} }
slot.onTake(playerIn, itemstack1); slot.onTake(playerIn, itemstack1);
@@ -102,9 +110,26 @@ public class RandomizerBagContainer extends Container {
@Override @Override
public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, EntityPlayer player) { public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, EntityPlayer player) {
// this will prevent the player from interacting with the item that opened the inventory: // this will prevent the player from interacting with the item that opened the inventory:
ItemStack clickItemStack = super.slotClick(slot, dragType, clickTypeIn, player);
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack() == player.getHeldItem(EnumHand.MAIN_HAND)) { if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack() == player.getHeldItem(EnumHand.MAIN_HAND)) {
return null; return ItemStack.EMPTY;
} }
return super.slotClick(slot, dragType, clickTypeIn, player); return clickItemStack;
} }
/**
* Callback for when the crafting gui is closed.
*/
// @Override
// public void onContainerClosed(EntityPlayer player)
// {
// if(player.inventory.getItemStack() != null)
// {
// player.entityDropItem(player.inventory.getItemStack(), 0.5f);
// }
// if(!player.world.isRemote)
// {
// detectAndSendChanges();
// }
// }
} }

View File

@@ -7,6 +7,7 @@ import net.minecraftforge.fml.common.network.IGuiHandler;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -17,8 +18,10 @@ public class RandomizerBagGuiHandler implements IGuiHandler {
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) { if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// Use the player's held item to create the container // Use the player's held item to create the container
return new RandomizerBagContainer(player.inventory, IItemHandler capability = player.getHeldItemMainhand().hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) ?
player.getHeldItem(EnumHand.MAIN_HAND).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)); player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) :
player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
return new RandomizerBagContainer(player.inventory, capability);
} }
return null; return null;
} }
@@ -29,8 +32,10 @@ public class RandomizerBagGuiHandler implements IGuiHandler {
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) { if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// Use the player's held item to create the client-side gui container // Use the player's held item to create the client-side gui container
return new RandomizerBagGuiContainer(player.inventory, IItemHandler capability = player.getHeldItemMainhand().hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) ?
player.getHeldItem(EnumHand.MAIN_HAND).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)); player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) :
player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
return new RandomizerBagGuiContainer(player.inventory, capability);
} }
return null; return null;
} }

View File

@@ -1,158 +1,50 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
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.client.gui.GuiTextField;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
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.Keyboard;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class SettingsGui extends GuiScreen { public class SettingsGui extends GuiScreen {
protected List<GuiTextField> textFieldList = new ArrayList<>(); private GuiScrollPane scrollPane;
private GuiButton buttonClose;
protected List<GuiButton> mirrorButtonList = new ArrayList<>(); private MirrorSettingsGui mirrorSettingsGui;
protected List<GuiTextField> mirrorTextFieldList = new ArrayList<>(); private ArraySettingsGui arraySettingsGui;
protected List<GuiTextField> arrayTextFieldList = new ArrayList<>();
private GuiTextField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius;
private GuiCheckBox buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ;
private GuiButton buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines;
private GuiButton buttonCurrentPosition, buttonClose;
private GuiCheckBox buttonArrayEnabled;
private GuiTextField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount;
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 GuiTextField(id++, fontRenderer, left + 70, y, 50, 18); scrollPane.listEntries.add(mirrorSettingsGui);
textMirrorPosX.setText("0.5");
mirrorTextFieldList.add(textMirrorPosX);
textMirrorPosY = new GuiTextField(id++, fontRenderer, left + 140, y, 50, 18); arraySettingsGui = new ArraySettingsGui(scrollPane);
textMirrorPosY.setText("64.5"); scrollPane.listEntries.add(arraySettingsGui);
mirrorTextFieldList.add(textMirrorPosY);
textMirrorPosZ = new GuiTextField(id++, fontRenderer, left + 210, y, 50, 18); id = scrollPane.initGui(id, buttonList);
textMirrorPosZ.setText("0.5");
mirrorTextFieldList.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 GuiTextField(id++, fontRenderer, left + 220, y, 60, 18);
textMirrorRadius.setText("50");
mirrorTextFieldList.add(textMirrorRadius);
y = top + 72;
buttonCurrentPosition = new GuiButton(id++, left + 5, y, 110, 20, "Set to current pos");
mirrorButtonList.add(buttonCurrentPosition);
buttonDrawLines = new GuiButton(id++, left + 127, y, 70, 20, "Show lines");
mirrorButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiButton(id++, left + 209, y, 75, 20, "Show area");
mirrorButtonList.add(buttonDrawPlanes);
//ARRAY
y = top + 100;
buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
buttonList.add(buttonArrayEnabled);
y = top + 120;
textArrayOffsetX = new GuiTextField(id++, fontRenderer, left + 70, y, 50, 18);
textArrayOffsetX.setText("0");
arrayTextFieldList.add(textArrayOffsetX);
textArrayOffsetY = new GuiTextField(id++, fontRenderer, left + 140, y, 50, 18);
textArrayOffsetY.setText("0");
arrayTextFieldList.add(textArrayOffsetY);
textArrayOffsetZ = new GuiTextField(id++, fontRenderer, left + 210, y, 50, 18);
textArrayOffsetZ.setText("0");
arrayTextFieldList.add(textArrayOffsetZ);
y = top + 150;
textArrayCount = new GuiTextField(id++, fontRenderer, left + 55, y, 50, 18);
textArrayCount.setText("5");
arrayTextFieldList.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.setText(String.valueOf(m.position.x));
textMirrorPosY.setText(String.valueOf(m.position.y));
textMirrorPosZ.setText(String.valueOf(m.position.z));
buttonMirrorX.setIsChecked(m.mirrorX);
buttonMirrorY.setIsChecked(m.mirrorY);
buttonMirrorZ.setIsChecked(m.mirrorZ);
textMirrorRadius.setText(String.valueOf(m.radius));
drawLines = m.drawLines;
drawPlanes = m.drawPlanes;
buttonDrawLines.displayString = drawLines ? "Hide lines" : "Show lines";
buttonDrawPlanes.displayString = drawPlanes ? "Hide area" : "Show area";
//ARRAY
Array.ArraySettings a = buildSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setText(String.valueOf(a.offset.getX()));
textArrayOffsetY.setText(String.valueOf(a.offset.getY()));
textArrayOffsetZ.setText(String.valueOf(a.offset.getZ()));
textArrayCount.setText(String.valueOf(a.count));
}
buttonList.addAll(mirrorButtonList);
textFieldList.addAll(mirrorTextFieldList);
textFieldList.addAll(arrayTextFieldList);
} }
@Override @Override
//Process general logic, i.e. hide buttons //Process general logic, i.e. hide buttons
public void updateScreen() { public void updateScreen() {
textFieldList.forEach(GuiTextField::updateCursorCounter); scrollPane.updateScreen();
} }
@Override @Override
@@ -161,154 +53,77 @@ 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 + 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 + 52;
fontRenderer.drawString("Direction", left + offset, y, 0xFFFFFF, true);
fontRenderer.drawString("Size", left + 190, y, 0xFFFFFF, true);
mirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorTextFieldList.forEach(textField -> textField.drawTextBox());
} 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);
arrayTextFieldList.forEach(textField -> textField.drawTextBox());
} else {
fontRenderer.drawString("Array disabled", left + offset, y, 0x999999, true);
}
buttonClose.drawButton(this.mc, mouseX, mouseY, partialTicks); buttonClose.drawButton(this.mc, mouseX, mouseY, partialTicks);
scrollPane.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);
if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK || keyCode == Keyboard.KEY_DELETE) { scrollPane.keyTyped(typedChar, keyCode);
for (GuiTextField textField : textFieldList) {
if (textField.isFocused()) {
textField.textboxKeyTyped(typedChar, keyCode);
}
}
}
if (keyCode == ClientProxy.keyBindings[0].getKeyCode()) { if (keyCode == ClientProxy.keyBindings[0].getKeyCode()) {
Minecraft.getMinecraft().player.closeScreen(); mc.player.closeScreen();
} }
} }
@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);
textFieldList.forEach(textField -> textField.mouseClicked(mouseX, mouseY, mouseButton)); scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
} }
@Override @Override
protected void actionPerformed(GuiButton button) throws IOException { protected void mouseReleased(int mouseX, int mouseY, int state) {
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state))
{
super.mouseReleased(mouseX, mouseY, state);
}
}
@Override
public void handleMouseInput() throws IOException {
super.handleMouseInput();
scrollPane.handleMouseInput();
//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
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.setText(String.valueOf(pos.x));
textMirrorPosY.setText(String.valueOf(pos.y));
textMirrorPosZ.setText(String.valueOf(pos.z));
}
if (button == buttonDrawLines) {
drawLines = !drawLines;
buttonDrawLines.displayString = drawLines ? "Hide lines" : "Show lines";
}
if (button == buttonDrawPlanes) {
drawPlanes = !drawPlanes;
buttonDrawPlanes.displayString = drawPlanes ? "Hide area" : "Show area";
}
} }
@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.5, 64.5, 0.5);
try {
mirrorPos = new Vec3d(Double.parseDouble(textMirrorPosX.getText()), Double.parseDouble(textMirrorPosY.getText()), Double.parseDouble(textMirrorPosZ.getText()));
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(Minecraft.getMinecraft().player, "Mirror position not valid.", true);
EffortlessBuilding.log("Mirror position not valid. Resetting to default.");
}
boolean mirrorX = buttonMirrorX.isChecked();
boolean mirrorY = buttonMirrorY.isChecked();
boolean mirrorZ = buttonMirrorZ.isChecked();
int mirrorRadius = 50;
try {
mirrorRadius = Math.min(Integer.parseInt(textMirrorRadius.getText()), Mirror.MAX_RADIUS);
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(Minecraft.getMinecraft().player, "Mirror radius not valid.", true);
EffortlessBuilding.log("Mirror radius not valid. Resetting to default.");
}
mirrorRadius = Math.max(1, mirrorRadius);
mirrorRadius = Math.min(Mirror.MAX_RADIUS, mirrorRadius);
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(Integer.parseInt(textArrayOffsetX.getText()), Integer.parseInt(textArrayOffsetY.getText()), Integer.parseInt(textArrayOffsetZ.getText()));
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(Minecraft.getMinecraft().player, "Array offset not valid.", true);
EffortlessBuilding.log("Array offset not valid. Resetting to default.");
}
int arrayCount = 5;
try {
arrayCount = Integer.parseInt(textArrayCount.getText());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(Minecraft.getMinecraft().player, "Array count not valid.", true);
EffortlessBuilding.log("Array count not valid. Resetting to default.");
}
arrayCount = Math.max(1, arrayCount);
arrayCount = Math.min(Array.MAX_COUNT, arrayCount);
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();
buildSettings.setMirrorSettings(m); buildSettings.setMirrorSettings(m);
buildSettings.setArraySettings(a); buildSettings.setArraySettings(a);
//Sanitize
String error = BuildSettingsManager.sanitize(buildSettings, mc.player);
if (!error.isEmpty()) EffortlessBuilding.log(mc.player, error);
BuildSettingsManager.setBuildSettings(mc.player, buildSettings); BuildSettingsManager.setBuildSettings(mc.player, buildSettings);
//Send to server //Send to server
EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings));
} }
} }

View File

@@ -0,0 +1,407 @@
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.renderer.*;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool;
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.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.*;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
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)
public class RenderHelper implements IWorldEventListener {
private static final Color colorX = new Color(255, 72, 52);
private static final Color colorY = new Color(67, 204, 51);
private static final Color colorZ = new Color(52, 247, 255);
private static final int lineAlpha = 200;
private static final int planeAlpha = 75;
private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
private static List<BlockPos> previousCoordinates;
private static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getMinecraft().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
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_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glLineWidth(2);
}
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.glPopMatrix();
}
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) {
renderBlockOutline(pos, pos);
}
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
public static void renderBlockOutline(BlockPos pos1, BlockPos pos2) {
GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f);
}
@SubscribeEvent
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
begin(event.getPartialTicks());
//Mirror lines and areas
beginLines();
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ))
{
Vec3d pos = m.position.add(epsilon);
int radius = m.radius;
if (m.mirrorX)
{
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes);
}
if (m.mirrorY)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes);
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ)))
{
drawMirrorLines(m);
}
}
endLines();
//Render block previews
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)
if (objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK)
{
beginBlockPreviews();
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
BlockPos startPos = objectMouseOver.getBlockPos();
//Check if tool (or none) in hand
ItemStack mainhand = player.getHeldItemMainhand();
boolean toolInHand = mainhand.isEmpty() || (!mainhand.isEmpty() && mainhand.getItem() instanceof ItemTool);
boolean replaceable =
player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!buildSettings.doQuickReplace() && !toolInHand && !replaceable) {
startPos = startPos.offset(objectMouseOver.sideHit);
}
//Get under tall grass and other replaceable blocks
if (buildSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down();
}
//get coordinates
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startPos);
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();
}
Vec3d hitVec = objectMouseOver.hitVec;
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z)));
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = BuildModifiers.findBlockStates(player, startPos, hitVec, objectMouseOver.sideHit, itemStacks);
//check if valid blockstates
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
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();
}
//----Mirror----
public static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
public static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
public static void drawMirrorLines(Mirror.MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
GL11.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
//IWORLDEVENTLISTENER IMPLEMENTATION
@Override
public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {
}
@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,12 +1,15 @@
package nl.requios.effortlessbuilding; 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;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Enchantments;
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;
@@ -14,11 +17,15 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
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.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
@@ -39,7 +46,7 @@ public class SurvivalHelper {
//Check if itemstack is correct //Check if itemstack is correct
if (!(itemstack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemstack.getItem()) != blockState.getBlock()) { if (!(itemstack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemstack.getItem()) != blockState.getBlock()) {
EffortlessBuilding.log(player, "Cannot replace block", true); EffortlessBuilding.log(player, "Cannot (re)place block", true);
EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemstack.toString() + " does not match blockstate " + blockState.toString()); EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemstack.toString() + " does not match blockstate " + blockState.toString());
return false; return false;
} }
@@ -103,12 +110,40 @@ 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);
if (blockState.getBlock().canHarvestBlock(world, pos, player)) return true; }
return false; //From ForgeHooks#canHarvestBlock
public static boolean canHarvestBlock(@Nonnull Block block, @Nonnull EntityPlayer player, @Nonnull IBlockAccess world, @Nonnull BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
if (state.getMaterial().isToolNotRequired())
{
return true;
}
ItemStack stack = player.getHeldItemMainhand();
String tool = block.getHarvestTool(state);
if (stack.isEmpty() || tool == null)
{
return player.canHarvestBlock(state);
}
if (stack.getItemDamage() >= stack.getMaxDamage()) return false;
int toolLevel = stack.getItem().getHarvestLevel(stack, tool, player, state);
if (toolLevel < 0)
{
return player.canHarvestBlock(state);
}
return toolLevel >= block.getHarvestLevel(state);
} }
//Can be harvested with hand? (or in creative) //Can be harvested with hand? (or in creative)
@@ -128,7 +163,8 @@ public class SurvivalHelper {
IBlockState blockState = world.getBlockState(pos); IBlockState blockState = world.getBlockState(pos);
List<ItemStack> drops = blockState.getBlock().getDrops(world, pos, blockState, 0); int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand());
List<ItemStack> drops = blockState.getBlock().getDrops(world, pos, blockState, fortune);
for (ItemStack drop : drops) for (ItemStack drop : drops)
{ {
ItemHandlerHelper.giveItemToPlayer(player, drop); ItemHandlerHelper.giveItemToPlayer(player, drop);
@@ -136,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);
@@ -171,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

@@ -6,7 +6,6 @@ import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs; import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer; 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.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
@@ -17,26 +16,23 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.Mirror;
import nl.requios.effortlessbuilding.SurvivalHelper;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider; import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
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");
@@ -90,25 +86,25 @@ public class ItemRandomizerBag extends Item {
@Override @Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) { public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
ItemStack bag = player.getHeldItem(hand);
if (player.isSneaking()) { if (player.isSneaking()) {
if (world.isRemote) return new ActionResult<>(EnumActionResult.SUCCESS, player.getHeldItem(hand)); if (world.isRemote) return new ActionResult<>(EnumActionResult.SUCCESS, bag);
//Open inventory //Open inventory
player.openGui(EffortlessBuilding.instance, EffortlessBuilding.RANDOMIZER_BAG_GUI, world, 0, 0, 0); player.openGui(EffortlessBuilding.instance, EffortlessBuilding.RANDOMIZER_BAG_GUI, world, 0, 0, 0);
} else { } else {
//Use item //Use item
//Get bag inventory //Get bag inventory
ItemStack bag = player.getHeldItem(hand);
IItemHandler bagInventory = getBagInventory(bag); IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null) if (bagInventory == null)
return new ActionResult<>(EnumActionResult.FAIL, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.FAIL, bag);
ItemStack toUse = pickRandomStack(bagInventory); ItemStack toUse = pickRandomStack(bagInventory);
if (toUse.isEmpty()) return new ActionResult<>(EnumActionResult.FAIL, player.getHeldItem(hand)); if (toUse.isEmpty()) return new ActionResult<>(EnumActionResult.FAIL, bag);
return toUse.useItemRightClick(world, player, hand); return toUse.useItemRightClick(world, player, hand);
} }
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, bag);
} }
/** /**
@@ -188,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

@@ -1,9 +1,7 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.IThreadListener; import net.minecraft.util.IThreadListener;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@@ -51,6 +49,8 @@ public class BuildSettingsMessage implements IMessage {
buf.writeInt(a.count); buf.writeInt(a.count);
buf.writeBoolean(buildSettings.doQuickReplace()); buf.writeBoolean(buildSettings.doQuickReplace());
buf.writeInt(buildSettings.getReachUpgrade());
} }
@Override @Override
@@ -73,7 +73,10 @@ public class BuildSettingsMessage implements IMessage {
Array.ArraySettings a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); Array.ArraySettings a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
boolean quickReplace = buf.readBoolean(); boolean quickReplace = buf.readBoolean();
buildSettings = new BuildSettings(m, a, quickReplace);
int reachUpgrade = buf.readInt();
buildSettings = new BuildSettings(m, a, quickReplace, reachUpgrade);
} }
// The params of the IMessageHandler are <REQ, REPLY> // The params of the IMessageHandler are <REQ, REPLY>
@@ -88,15 +91,9 @@ public class BuildSettingsMessage implements IMessage {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// The value that was sent // The value that was sent
BuildSettings buildSettings = message.buildSettings; BuildSettings buildSettings = message.buildSettings;
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
Array.ArraySettings a = buildSettings.getArraySettings();
// Sanitize // Sanitize
m.radius = Math.min(m.radius, Mirror.MAX_RADIUS); BuildSettingsManager.sanitize(buildSettings, player);
m.radius = Math.max(1, m.radius);
a.count = Math.min(a.count, Array.MAX_COUNT);
a.count = Math.max(0, a.count);
// Execute the action on the main server thread by adding it as a scheduled task // Execute the action on the main server thread by adding it as a scheduled task
IThreadListener threadListener = EffortlessBuilding.proxy.getThreadListenerFromContext(ctx); IThreadListener threadListener = EffortlessBuilding.proxy.getThreadListenerFromContext(ctx);

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,27 +99,41 @@ 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) {
// check each enumerated key binding type for pressed and take appropriate action
EntityPlayerSP player = Minecraft.getMinecraft().player; EntityPlayerSP player = Minecraft.getMinecraft().player;
//Remember to send packet to server if necessary
//Show HUD
if (keyBindings[0].isPressed()) { if (keyBindings[0].isPressed()) {
// do stuff for this key binding here //Disabled if max reach is 0, might be set in the config that way.
// remember you may need to send packet to server if (BuildSettingsManager.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Effortless Building is disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else {
if (Minecraft.getMinecraft().currentScreen == null) { if (Minecraft.getMinecraft().currentScreen == null) {
Minecraft.getMinecraft().displayGuiScreen(new SettingsGui()); Minecraft.getMinecraft().displayGuiScreen(new SettingsGui());
} else { } else {
player.closeScreen(); player.closeScreen();
} }
} }
}
//QuickReplace toggle
if (keyBindings[1].isPressed()) { if (keyBindings[1].isPressed()) {
// do stuff for this key binding here
// remember you may need to send packet to server
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
buildSettings.setQuickReplace(!buildSettings.doQuickReplace()); buildSettings.setQuickReplace(!buildSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (buildSettings.doQuickReplace() ? "on" : "off")); EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (buildSettings.doQuickReplace() ? "on" : "off"));
EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings));
} }
//Creative/survival mode toggle
if (keyBindings[2].isPressed()) { if (keyBindings[2].isPressed()) {
if (player.isCreative()) { if (player.isCreative()) {
player.sendChatMessage("/gamemode 0"); player.sendChatMessage("/gamemode 0");
@@ -120,7 +147,10 @@ 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)
if (objectMouseOver == null) return; if (objectMouseOver == null) return;
if (currentLookAt == null) { if (currentLookAt == null) {
@@ -140,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
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -2,7 +2,7 @@
{ {
"modid": "effortlessbuilding", "modid": "effortlessbuilding",
"name": "Effortless Building", "name": "Effortless Building",
"description": "Makes building easier by providing tools like mirrors, arrays, quickreplace and a block randomizer.", "description": "Makes building easier by providing tools like mirrors, arrays, QuickReplace and a block randomizer. For survival and creative mode.",
"version": "${version}", "version": "${version}",
"mcversion": "${mcversion}", "mcversion": "${mcversion}",
"url": "https://minecraft.curseforge.com/projects/effortless-building", "url": "https://minecraft.curseforge.com/projects/effortless-building",