23 Commits

Author SHA1 Message Date
Christian Knaapen
346fc6d533 Fixed mouse clicks in Modifier Settings sometimes being in the wrong place.
Fixed typing in multiple text fields at once.
2019-02-28 18:25:39 +01:00
Christian Knaapen
6678405c75 Settings are saved across dimensions (including reach upgrades, issue #12).
Fixed silk touch, shearing leaves, dropping bed etc. (issue #15)
Items dont drop directly to inventory anymore because of above fix, might be re-added later.
Can no longer place blocks in entities (including the player).
Added support for changing config ingame.
Added preliminary ArchitectureCraft compatibility (places right type, not rotation yet).
Updated forge.
2019-02-14 14:57:28 +01:00
Christian Knaapen
d07751a01f Fixed issue #8 Craft when activating the menu.
Fixed being able to mine bedrock. Whoops.
Fixed grass and flowers instabreaking other blocks.
2019-01-11 03:01:04 +01:00
Christian Knaapen
f3ad36e6a6 Fixed rotation and various small bugs. 2019-01-10 17:21:56 +01:00
Christian Knaapen
aeb4df6156 Added rotation to blocks placed with radial mirror.
Added alternative mode where every other slice of the radial mirror is mirrored.
Fixed issue #6 Crash when creating new world after first launch.
2019-01-08 18:53:12 +01:00
Christian Knaapen
8230f93b0c Added radial mirror with position, slices, and radius. With GUI, capability and network.
Optimized imports.
2019-01-04 17:06:58 +01:00
Christian Knaapen
3d3a90e76f Message when using reach upgrades in creative.
Sound when placing blocks far away.
2019-01-02 17:05:51 +01:00
Christian Knaapen
36a698cd95 Increased range for placing and breaking blocks (breaking at range only in creative).
Added reach upgrade items.
Added reach command (usage: /reach <level>).
2018-12-23 22:15:05 +01:00
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
Christian Knaapen
bda53e4b08 Check if can break and replace blocks. Breaking only works if your current held tool can break it. Replace only works with blocks that can be harvested with your hand.
Damages used tool appropriately.
Added block outlines to mirror and array.
2018-10-20 16:15:14 +02:00
Christian Knaapen
821b46a253 Fixed shrinking itemstack with mirror/array when not using quickreplace.
Fixed replacing same blocks dropping extra.
2018-10-18 16:50:39 +02:00
Christian Knaapen
0e7d08438d Fixed randomizer bag not working with quickreplace. 2018-10-14 15:46:06 +02:00
Christian Knaapen
483d6cc53e Checks if placeBlock is allowed. Fixed stutter on line rendering. Added toggle for creative/survival mode. 2018-10-06 20:20:10 +02:00
54 changed files with 4029 additions and 952 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.1.3" version = "1.0.3"
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"
@@ -21,7 +21,7 @@ compileJava {
} }
minecraft { minecraft {
version = "1.12.2-14.23.4.2705" version = "1.12.2-14.23.5.2768"
runDir = "run" runDir = "run"
// the mappings can be changed at any time, and must be in the following format. // the mappings can be changed at any time, and must be in the following format.
@@ -29,7 +29,7 @@ minecraft {
// stable_# stables are built at the discretion of the MCP team. // stable_# stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not always work. // Use non-default mappings at your own risk. they may not always work.
// simply re-run your setup task after changing the mappings to update your workspace. // simply re-run your setup task after changing the mappings to update your workspace.
mappings = "snapshot_20171003" mappings = "stable_39"
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
} }

View File

@@ -1,28 +1,27 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.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.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import java.util.ArrayList;
import java.util.List;
public class Array { public class Array {
//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;
public BlockPos offset = BlockPos.ORIGIN; public BlockPos offset = BlockPos.ORIGIN;
public int count = 5; public int count = 5;
public ArraySettings(){ public ArraySettings() {
} }
public ArraySettings(boolean enabled, BlockPos offset, int count) { public ArraySettings(boolean enabled, BlockPos offset, int count) {
@@ -30,84 +29,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 void onBlockPlaced(BlockEvent.PlaceEvent event) { List<BlockPos> coordinates = new ArrayList<>();
if (event.getWorld().isRemote) return;
//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; if (!isEnabled(a)) return blockStates;
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return; 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;
//Check if held block = placed block (otherwise its a bag or wand) //Randomizer bag synergy
if (!event.getPlayer().isCreative() && Block.getBlockFromItem(itemStack.getItem()) == event.getPlacedBlock().getBlock()) { if (bagInventory != null) {
itemStack.shrink(1); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
} blockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
//Randomizer bag synergy
IBlockState blockState = bagInventory == null ? event.getPlacedBlock() :
getBlockStateFromRandomizerBag(bagInventory, event.getWorld(), event.getPlayer(), event.getPos());
//TODO check if can place (ItemBlock) and if can break replaced
//Drop existing block
SurvivalHelper.dropBlock(event.getWorld(), pos, event.getPlayer());
event.getWorld().setBlockState(pos, blockState);
} }
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
blockStates.add(blockState);
itemStacks.add(itemStack);
} }
//EffortlessBuilding.log(event.getPlayer(), String.valueOf(event.getPlayer().getHeldItem(event.getHand()).getCount()));
return blockStates;
} }
private static IBlockState getBlockStateFromRandomizerBag(IItemHandler bagInventory, World world, EntityPlayer player, BlockPos pos) { public static boolean isEnabled(ArraySettings a) {
int randomSlot = ItemRandomizerBag.pickRandomSlot(bagInventory); if (a == null || !a.enabled) return false;
ItemStack stack = bagInventory.getStackInSlot(randomSlot);
//TODO get facing from getPlacedAgainst and getPlacedBlock if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return false;
return Block.getBlockFromItem(stack.getItem()).getStateForPlacement(world, pos, EnumFacing.NORTH, 0, 0, 0, stack.getMetadata(), player, EnumHand.MAIN_HAND);
return true;
} }
//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);
if (event.getWorld().isBlockLoaded(pos, false)) {
//TODO check if can break
//Drop existing block
SurvivalHelper.dropBlock(event.getWorld(), pos, event.getPlayer());
event.getWorld().setBlockToAir(pos);
}
}
}
} }

View File

@@ -0,0 +1,62 @@
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.",
"Enable the crafting of reach upgrades to increase reach.",
"If disabled, reach is set to level 3 for survival players."})
public boolean enableReachUpgrades = true;
@Comment({"Maximum reach in creative",
"Keep in mind that chunks need to be loaded to be able to place blocks inside."})
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({"Allows a survival player to break blocks that are far away, in addition to placing blocks.",
"Note: this allows insta-breaking of blocks in survival."})
public boolean breakFar = false;
@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,216 @@
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.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import java.util.ArrayList;
import java.util.List;
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();
}
//Check if player reach does not exceed startpos
int maxReach = ReachHelper.getMaxReach(player);
if (player.getPosition().distanceSq(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
//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, hitVec, false, 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);
}
}
//Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) {
BlockPos blockPos = message.getBlockPos();
if (ReachHelper.canBreakFar(player) && message.isBlockHit()) {
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(player.world, blockPos, player.world.getBlockState(blockPos), player);
onBlockBroken(event);
}
}
public static void onBlockBroken(BlockEvent.BreakEvent event) {
World world = event.getWorld();
BlockPos pos = event.getPos();
if (world.isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own break event if anything is enabled
if (isEnabled(buildSettings, pos)) {
//get coordinates
List<BlockPos> coordinates = findCoordinates(event.getPlayer(), pos);
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = world.getBlockState(pos).getBlockHardness(
world, pos) == 0f;
//break all those blocks
for (BlockPos coordinate : coordinates) {
if (world.isBlockLoaded(coordinate, false)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, 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));
coordinates.addAll(RadialMirror.findCoordinates(player, startPos));
//get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.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));
blockStates.addAll(RadialMirror.findBlockStates(player, startPos, blockState, itemStack, itemStacks));
//add mirror for each array 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));
blockStates.addAll(RadialMirror.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()) ||
RadialMirror.isEnabled(buildSettings.getRadialMirrorSettings(), startPos) ||
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,66 +5,147 @@ 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.helper.ReachHelper;
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 = ReachHelper.getMaxReach(player);
String error = "";
//Mirror settings
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m.radius < 1) {
m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. ";
}
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to "+ (maxReach / 2) + ". ";
}
//Array settings
Array.ArraySettings a = buildSettings.getArraySettings();
if (a.count < 0) {
a.count = 0;
error += "Array count may not be negative. It has been reset to 0.";
}
if (a.getReach() > maxReach) {
a.count = 0;
error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. ";
}
//Radial mirror settings
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
if (r.slices < 2) {
r.slices = 2;
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
}
if (r.radius < 1) {
r.radius = 1;
error += "Radial mirror radius has to be at least 1. This has been corrected. ";
}
if (r.getReach() > maxReach) {
r.radius = maxReach / 2;
error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to "+ (maxReach / 2) + ". ";
}
//Other
if (buildSettings.reachUpgrade < 0) {
buildSettings.reachUpgrade = 0;
}
if (buildSettings.reachUpgrade > 3) {
buildSettings.reachUpgrade = 3;
}
return error;
}
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 RadialMirror.RadialMirrorSettings radialMirrorSettings;
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();
radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
} }
public BuildSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings, boolean quickReplace) { public BuildSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
this.mirrorSettings = mirrorSettings; this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings; this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings;
this.quickReplace = quickReplace; this.quickReplace = quickReplace;
this.reachUpgrade = reachUpgrade;
} }
public Mirror.MirrorSettings getMirrorSettings() { public Mirror.MirrorSettings getMirrorSettings() {
return mirrorSettings; if (this.mirrorSettings == null) this.mirrorSettings = new Mirror.MirrorSettings();
return this.mirrorSettings;
} }
public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) { public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) {
if (mirrorSettings == null) return;
this.mirrorSettings = mirrorSettings; this.mirrorSettings = mirrorSettings;
} }
public Array.ArraySettings getArraySettings() { public Array.ArraySettings getArraySettings() {
return arraySettings; if (this.arraySettings == null) this.arraySettings = new Array.ArraySettings();
return this.arraySettings;
} }
public void setArraySettings(Array.ArraySettings arraySettings) { public void setArraySettings(Array.ArraySettings arraySettings) {
if (arraySettings == null) return;
this.arraySettings = arraySettings; this.arraySettings = arraySettings;
} }
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
return this.radialMirrorSettings;
}
public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) {
if (radialMirrorSettings == null) return;
this.radialMirrorSettings = radialMirrorSettings;
}
public boolean doQuickReplace() { public boolean doQuickReplace() {
return quickReplace; return quickReplace;
} }
@@ -72,6 +153,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
@@ -86,6 +175,12 @@ public class BuildSettingsManager {
handleNewPlayer(player); handleNewPlayer(player);
} }
@SubscribeEvent
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
EntityPlayer player = event.player;
handleNewPlayer(player);
}
private static void handleNewPlayer(EntityPlayer player){ private static void handleNewPlayer(EntityPlayer player){
if (getBuildSettings(player) == null) { if (getBuildSettings(player) == null) {
setBuildSettings(player, new BuildSettings()); setBuildSettings(player, new BuildSettings());

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;
@@ -15,11 +17,16 @@ import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.capability.*; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.command.CommandReach;
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.item.ItemReachUpgrade1;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade2;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade3;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.network.QuickReplaceMessage;
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 +36,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.1.3"; public static final String VERSION = "1.0.3";
@Mod.Instance(EffortlessBuilding.MODID) @Mod.Instance(EffortlessBuilding.MODID)
public static EffortlessBuilding instance; public static EffortlessBuilding instance;
@@ -45,12 +52,18 @@ public class EffortlessBuilding
public static final SimpleNetworkWrapper packetHandler = NetworkRegistry.INSTANCE.newSimpleChannel(EffortlessBuilding.MODID); public static final SimpleNetworkWrapper packetHandler = NetworkRegistry.INSTANCE.newSimpleChannel(EffortlessBuilding.MODID);
public static final ItemRandomizerBag ITEM_RANDOMIZER_BAG = new ItemRandomizerBag(); public static final ItemRandomizerBag ITEM_RANDOMIZER_BAG = new ItemRandomizerBag();
public static final ItemReachUpgrade1 ITEM_REACH_UPGRADE_1 = new ItemReachUpgrade1();
public static final ItemReachUpgrade2 ITEM_REACH_UPGRADE_2 = new ItemReachUpgrade2();
public static final ItemReachUpgrade3 ITEM_REACH_UPGRADE_3 = new ItemReachUpgrade3();
public static final Block[] BLOCKS = { public static final Block[] BLOCKS = {
}; };
public static final Item[] ITEMS = { public static final Item[] ITEMS = {
ITEM_RANDOMIZER_BAG ITEM_RANDOMIZER_BAG,
ITEM_REACH_UPGRADE_1,
ITEM_REACH_UPGRADE_2,
ITEM_REACH_UPGRADE_3
}; };
public static final int RANDOMIZER_BAG_GUI = 0; public static final int RANDOMIZER_BAG_GUI = 0;
@@ -61,13 +74,16 @@ 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);
EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 2, Side.SERVER);
proxy.preInit(event); proxy.preInit(event);
} }
@@ -77,7 +93,9 @@ 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);
} }
@@ -91,6 +109,7 @@ public class EffortlessBuilding
@EventHandler @EventHandler
public void serverStarting(FMLServerStartingEvent event) public void serverStarting(FMLServerStartingEvent event)
{ {
event.registerServerCommand(new CommandReach());
proxy.serverStarting(event); proxy.serverStarting(event);
} }

View File

@@ -1,23 +1,32 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
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.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 nl.requios.effortlessbuilding.capability.BuildModifierCapability; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import java.util.List;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class EventHandler public class EventHandler
{ {
@SubscribeEvent @SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) public static void registerBlocks(RegistryEvent.Register<Block> event)
{ {
@@ -38,24 +47,69 @@ 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
public static void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event)
{
if (event.getModID().equals(EffortlessBuilding.MODID))
{
ConfigManager.sync(EffortlessBuilding.MODID, Config.Type.INSTANCE);
}
}
// @SubscribeEvent
// public static void onServerTick(TickEvent.ServerTickEvent event) {
//
// }
@SubscribeEvent @SubscribeEvent
public static void onBlockPlaced(BlockEvent.PlaceEvent event) { public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
QuickReplace.onBlockPlaced(event); //Still call it to cancel event
if (event.isCanceled()) return; BuildModifiers.onBlockPlaced(event);
Mirror.onBlockPlaced(event);
Array.onBlockPlaced(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);
if (originalBlockHardness < 0) return; //Dont break bedrock
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

@@ -1,50 +1,30 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.block.*; import net.minecraft.block.BlockDirectional;
import net.minecraft.block.BlockDispenser;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.BlockStairs;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
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.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.common.util.BlockSnapshot;
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.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() {
} }
@@ -59,123 +39,147 @@ public class Mirror {
this.drawLines = drawLines; this.drawLines = drawLines;
this.drawPlanes = drawPlanes; this.drawPlanes = drawPlanes;
} }
public int getReach() {
return radius * 2;
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
//find mirrorsettings for the player
MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return coordinates;
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates);
return coordinates;
} }
//Called from EventHandler private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
public static void onBlockPlaced(BlockEvent.PlaceEvent event) { //find mirror position
if (event.getWorld().isRemote) return; double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
coordinates.add(newBlockPos);
//find mirrorsettings for the player that placed the block if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates);
MirrorSettings m = BuildSettingsManager.getBuildSettings(event.getPlayer()).getMirrorSettings(); if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
if (m == null) return; }
if (!m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return; 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 within mirror distance, mirror if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, 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 coordinateMirrorZ(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 z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
return; 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); 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);
if (m.mirrorY) { return blockStates;
placeMirrorY(event.getWorld(), event.getPlayer(), m, oldBlockPos, event.getPlacedBlock(), bagInventory);
}
if (m.mirrorZ) {
placeMirrorZ(event.getWorld(), event.getPlayer(), m, oldBlockPos, event.getPlacedBlock(), bagInventory);
}
} }
private static IBlockState getBlockStateFromRandomizerBag(IItemHandler bagInventory, World world, EntityPlayer player, BlockPos pos) { private static void blockStateMirrorX(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
int randomSlot = ItemRandomizerBag.pickRandomSlot(bagInventory); IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
ItemStack stack = bagInventory.getStackInSlot(randomSlot);
//TODO get facing from getPlacedAgainst and getPlacedBlock
return Block.getBlockFromItem(stack.getItem()).getStateForPlacement(world, pos, EnumFacing.NORTH, 0, 0, 0, stack.getMetadata(), player, EnumHand.MAIN_HAND);
}
private static void placeMirrorX(World world, EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState, IItemHandler bagInventory) {
//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());
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) if (bagInventory != null) {
oldBlockState = getBlockStateFromRandomizerBag(bagInventory, world, player, oldBlockPos); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
IBlockState newBlockState = oldBlockState.withMirror(net.minecraft.util.Mirror.FRONT_BACK);
//place block
if (world.isBlockLoaded(newBlockPos, true)) {
placeBlock(world, player, newBlockPos, newBlockState);
} }
if (m.mirrorY) placeMirrorY(world, player, m, newBlockPos, newBlockState, bagInventory);
if (m.mirrorZ) placeMirrorZ(world, player, m, newBlockPos, newBlockState, bagInventory); //Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.withMirror(net.minecraft.util.Mirror.FRONT_BACK);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(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) { 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());
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) if (bagInventory != null) {
oldBlockState = getBlockStateFromRandomizerBag(bagInventory, world, player, oldBlockPos); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
IBlockState newBlockState = getVerticalMirror(oldBlockState);
//place block
if (world.isBlockLoaded(newBlockPos, true)) {
placeBlock(world, player, newBlockPos, newBlockState);
} }
if (m.mirrorZ) placeMirrorZ(world, player, m, newBlockPos, newBlockState, bagInventory);
//Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState);
//Store blockstate and itemstack
blockStates.add(newBlockState);
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) { 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);
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) if (bagInventory != null) {
oldBlockState = getBlockStateFromRandomizerBag(bagInventory, world, player, oldBlockPos); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
IBlockState newBlockState = oldBlockState.withMirror(net.minecraft.util.Mirror.LEFT_RIGHT);
//place block
if (world.isBlockLoaded(newBlockPos, true)) {
placeBlock(world, player, newBlockPos, newBlockState);
} }
//Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.withMirror(net.minecraft.util.Mirror.LEFT_RIGHT);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
} }
private static void placeBlock(World world, EntityPlayer player, BlockPos newBlockPos, IBlockState newBlockState) { public static boolean isEnabled(MirrorSettings m, BlockPos startPos) {
//Check itemstack if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false;
ItemStack itemStack = player.getHeldItem(player.swingingHand); //TODO check hand
if (itemStack.isEmpty()) return;
//TODO check if can place //within mirror distance
//TODO check if can break if (startPos.getX() + 0.5 < m.position.x - m.radius || startPos.getX() + 0.5 > m.position.x + m.radius ||
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.dropBlock(world, newBlockPos, player); return true;
world.setBlockState(newBlockPos, newBlockState);
//Check if held block = placed block (otherwise its a bag or wand)
if (!player.isCreative() && Block.getBlockFromItem(itemStack.getItem()) == newBlockState.getBlock()) {
itemStack.shrink(1);
}
//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) {
@@ -218,252 +222,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
if (event.getWorld().isBlockLoaded(newBlockPos, true)) {
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());
//place block
if (event.getWorld().isBlockLoaded(newBlockPos, true)) {
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);
//place block
if (event.getWorld().isBlockLoaded(newBlockPos, true)) {
breakBlock(event, newBlockPos);
}
}
private static void breakBlock(BlockEvent.BreakEvent event, BlockPos newBlockPos) {
//TODO check if can break
SurvivalHelper.dropBlock(event.getWorld(), newBlockPos, event.getPlayer());
event.getWorld().setBlockToAir(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;
Vec3d playerPos = new Vec3d(player.posX, player.posY, player.posZ);
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(playerPos, 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(playerPos, 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(playerPos, 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(playerPos, m);
}
}
@SideOnly(Side.CLIENT)
public static void drawMirrorPlane(Vec3d playerPos, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
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.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
GL11.glLineWidth(2);
GL11.glDepthMask(false);
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();
}
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
@SideOnly(Side.CLIENT)
public static void drawMirrorPlaneY(Vec3d playerPos, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
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.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
GL11.glLineWidth(2);
GL11.glDepthMask(false);
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();
}
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
@SideOnly(Side.CLIENT)
public static void drawMirrorLines(Vec3d playerPos, MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
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.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
GL11.glDepthMask(false);
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();
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
} }

View File

@@ -1,76 +0,0 @@
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.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 blockstate 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<>();
public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
if (event.getWorld().isRemote) return;
//Only serverside
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
if (!buildSettings.doQuickReplace()) return;
//TODO base on player facing instead, no more messages (or break block clientside)
blockStates.put(event.getPlayer().getUniqueID(), event.getPlacedBlock());
//RayTraceResult result = event.getWorld().rayTraceBlocks(event.getPlayer().getPositionEyes(1f), event.getPlayer().getLookVec());
EffortlessBuilding.packetHandler.sendTo(new QuickReplaceMessage(), (EntityPlayerMP) event.getPlayer());
event.setCanceled(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());
SurvivalHelper.dropBlock(player.world, placedAgainstBlockPos, player);
player.world.setBlockState(placedAgainstBlockPos, blockState);
//Shrink itemstack with 1
ItemStack itemStack = player.getHeldItem(player.swingingHand); //TODO check hand
if (!player.isCreative() && Block.getBlockFromItem(itemStack.getItem()) == blockState.getBlock()) {
itemStack.shrink(1);
}
//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

@@ -0,0 +1,194 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import java.util.ArrayList;
import java.util.List;
public class RadialMirror {
public static class RadialMirrorSettings {
public boolean enabled = false;
public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true, drawPlanes = false;
public RadialMirrorSettings() {
}
public RadialMirrorSettings(boolean enabled, Vec3d position, int slices, boolean alternate, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = enabled;
this.position = position;
this.slices = slices;
this.alternate = alternate;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() {
return radius * 2;
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
//find radial mirror settings for the player
RadialMirrorSettings r = BuildSettingsManager.getBuildSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return coordinates;
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
Vec3d startVec = new Vec3d(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3d relStartVec = startVec.subtract(r.position);
double startAngleToCenter = MathHelper.atan2(relStartVec.x, relStartVec.z);
if (startAngleToCenter < 0) startAngleToCenter += Math.PI;
double startAngleInSlice = startAngleToCenter % sliceAngle;
for (int i = 1; i < r.slices; i++) {
double curAngle = sliceAngle * i;
//alternate mirroring of slices
if (r.alternate && i%2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
Vec3d relNewVec = relStartVec.rotateYaw((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (!coordinates.contains(newBlockPos) && !newBlockPos.equals(startPos)) coordinates.add(newBlockPos);
}
return coordinates;
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, IBlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//find radial mirror settings for the player that placed the block
RadialMirrorSettings r = BuildSettingsManager.getBuildSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return blockStates;
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
Vec3d startVec = new Vec3d(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3d relStartVec = startVec.subtract(r.position);
double startAngleToCenter = MathHelper.atan2(relStartVec.x, relStartVec.z);
double startAngleToCenterMod = startAngleToCenter < 0 ? startAngleToCenter + Math.PI : startAngleToCenter;
double startAngleInSlice = startAngleToCenterMod % sliceAngle;
//Rotate the original blockstate
blockState = rotateOriginalBlockState(startAngleToCenter, blockState);
//Randomizer bag synergy
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
}
IBlockState newBlockState;
for (int i = 1; i < r.slices; i++) {
newBlockState = blockState;
double curAngle = sliceAngle * i;
//alternate mirroring of slices
if (r.alternate && i%2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
Vec3d relNewVec = relStartVec.rotateYaw((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (coordinates.contains(newBlockPos) || newBlockPos.equals(startPos)) continue; //filter out duplicates
coordinates.add(newBlockPos);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
newBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState);
}
//rotate
newBlockState = rotateBlockState(relNewVec, newBlockState, r.alternate && i%2 == 1);
blockStates.add(newBlockState);
itemStacks.add(itemStack);
}
return blockStates;
}
private static IBlockState rotateOriginalBlockState(double startAngleToCenter, IBlockState blockState) {
IBlockState newBlockState = blockState;
if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.withRotation(Rotation.CLOCKWISE_180);
} else if (startAngleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.withRotation(Rotation.COUNTERCLOCKWISE_90);
} else if (startAngleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.withRotation(Rotation.CLOCKWISE_90);
}
return newBlockState;
}
private static IBlockState rotateBlockState(Vec3d relVec, IBlockState blockState, boolean alternate) {
IBlockState newBlockState;
double angleToCenter = MathHelper.atan2(relVec.x, relVec.z); //between -PI and PI
if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.withRotation(Rotation.CLOCKWISE_180);
if (alternate) {
newBlockState = newBlockState.withMirror(Mirror.FRONT_BACK);
}
} else if (angleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.withRotation(Rotation.CLOCKWISE_90);
if (alternate) {
newBlockState = newBlockState.withMirror(Mirror.LEFT_RIGHT);
}
} else if (angleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.withRotation(Rotation.COUNTERCLOCKWISE_90);
if (alternate) {
newBlockState = newBlockState.withMirror(Mirror.LEFT_RIGHT);
}
} else {
newBlockState = blockState;
if (alternate) {
newBlockState = newBlockState.withMirror(Mirror.FRONT_BACK);
}
}
return newBlockState;
}
public static boolean isEnabled(RadialMirrorSettings r, BlockPos startPos) {
if (r == null || !r.enabled) return false;
if (new Vec3d(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(r.position).lengthSquared() >
r.radius * r.radius)
return false;
return true;
}
}

View File

@@ -1,35 +0,0 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.ItemHandlerHelper;
import java.util.List;
public class SurvivalHelper {
public static boolean canBreak(){
return true;
}
public static boolean canPlace(){
return true;
}
//Gives items directly to player
public static void dropBlock(World world, BlockPos pos, EntityPlayer player){
if (player.isCreative()) return;
IBlockState blockState = world.getBlockState(pos);
List<ItemStack> drops = blockState.getBlock().getDrops(world, pos, blockState, 0);
for (ItemStack drop : drops)
{
ItemHandlerHelper.giveItemToPlayer(player, drop);
}
}
}

View File

@@ -14,23 +14,24 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.Array; import nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings; import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings;
import nl.requios.effortlessbuilding.Mirror; import nl.requios.effortlessbuilding.Mirror;
import nl.requios.effortlessbuilding.RadialMirror;
import javax.annotation.Nonnull; 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,14 +45,16 @@ 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();
if (m == null) m = new Mirror.MirrorSettings();
compound.setBoolean("mirrorEnabled", m.enabled); compound.setBoolean("mirrorEnabled", m.enabled);
compound.setDouble("mirrorPosX", m.position.x); compound.setDouble("mirrorPosX", m.position.x);
compound.setDouble("mirrorPosY", m.position.y); compound.setDouble("mirrorPosY", m.position.y);
@@ -65,18 +68,35 @@ public class BuildModifierCapability {
//ARRAY //ARRAY
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = buildSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings();
compound.setBoolean("arrayEnabled", a.enabled); compound.setBoolean("arrayEnabled", a.enabled);
compound.setInteger("arrayOffsetX", a.offset.getX()); compound.setInteger("arrayOffsetX", a.offset.getX());
compound.setInteger("arrayOffsetY", a.offset.getY()); compound.setInteger("arrayOffsetY", a.offset.getY());
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
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.setBoolean("radialMirrorEnabled", r.enabled);
compound.setDouble("radialMirrorPosX", r.position.x);
compound.setDouble("radialMirrorPosY", r.position.y);
compound.setDouble("radialMirrorPosZ", r.position.z);
compound.setInteger("radialMirrorSlices", r.slices);
compound.setBoolean("radialMirrorAlternate", r.alternate);
compound.setInteger("radialMirrorRadius", r.radius);
compound.setBoolean("radialMirrorDrawLines", r.drawLines);
compound.setBoolean("radialMirrorDrawPlanes", r.drawPlanes);
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 +116,56 @@ 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); //RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3d radialMirrorPosition = new Vec3d(compound.getDouble("radialMirrorPosX"), compound.getDouble("radialMirrorPosY"), compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInteger("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInteger("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
BuildSettings buildSettings = new BuildSettings(mirrorSettings, arraySettings, radialMirrorSettings, 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,43 @@
package nl.requios.effortlessbuilding.command;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.WrongUsageException;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
public class CommandReach extends CommandBase {
@Override
public String getName() {
return "reach";
}
@Override
public String getUsage(ICommandSender sender) {
return "commands.reach.usage";
}
@Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
if (args.length != 1) {
throw new WrongUsageException("commands.reach.usage");
}
if (sender instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) sender;
//Set reach level to args[0]
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
buildSettings.setReachUpgrade(Integer.valueOf(args[0]));
BuildSettingsManager.setBuildSettings(player, buildSettings);
//Send to client
EffortlessBuilding.packetHandler.sendTo(new BuildSettingsMessage(buildSettings), player);
sender.sendMessage(new TextComponentString("Reach level of " + sender.getName() + " set to " + buildSettings.getReachUpgrade()));
}
}
}

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 nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException;
import java.util.ArrayList;
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 = ReachHelper.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 a valid number.");
}
int arrayCount = 5;
try {
arrayCount = (int) textArrayCount.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array count not a valid number.");
}
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,151 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.util.text.TextFormatting;
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,465 @@
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 = getRelativeMouseY(mouseY, 0);
//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)
{
int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
int relativeX = getRelativeMouseX(mouseX);
//Always pass through mouseclicked, to be able to unfocus textfields
for (int i = 0; i < this.listEntries.size(); i++) {
int relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mousePressed(selectedSlot, mouseX, mouseY, mouseEvent, relativeX, relativeY);
}
// if (this.isMouseYWithinSlotBounds(mouseY))
// {
// int i = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
//
// if (i >= 0)
// {
// int relativeX = getRelativeMouseX(mouseX);
// int relativeY = getRelativeMouseY(mouseY, i);
//
// 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 relativeX = getRelativeMouseX(mouseX);
int relativeY = getRelativeMouseY(mouseY, i);
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 slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
int relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
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 slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
int relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
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;
}
}
private int getRelativeMouseX(int mouseX) {
int j = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
return mouseX - j;
}
private int getRelativeMouseY(int mouseY, int contentIndex) {
int k = this.top + 4 - this.getAmountScrolled() + getContentHeight(contentIndex) + this.headerPadding;
int relativeMouseY = mouseY - k;
//Content might be centered, adjust relative mouse y accordingly
int contentHeight = getContentHeight();
int insideHeight = this.bottom - this.top - 4;
if (contentHeight < insideHeight) {
//it fits, so we can center it vertically
relativeMouseY -= (insideHeight - contentHeight) / 2;
}
return relativeMouseY;
}
//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,295 @@
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 nl.requios.effortlessbuilding.helper.ReachHelper;
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 + ReachHelper.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("Radius", 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 a valid number.");
}
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 a valid number.");
}
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

@@ -0,0 +1,302 @@
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.RadialMirror;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected List<GuiButton> radialMirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> radialMirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> radialMirrorNumberFieldList = new ArrayList<>();
private GuiNumberField textRadialMirrorPosX, textRadialMirrorPosY, textRadialMirrorPosZ, textRadialMirrorSlices, textRadialMirrorRadius;
private GuiCheckBox buttonRadialMirrorEnabled, buttonRadialMirrorAlternate;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
public RadialMirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
id = super.initGui(id, buttonList);
int y = top - 2;
buttonRadialMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
buttonList.add(buttonRadialMirrorEnabled);
y = top + 18;
textRadialMirrorPosX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 58, y, 62, 18);
textRadialMirrorPosX.setNumber(0);
textRadialMirrorPosX.setTooltip(
Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
radialMirrorNumberFieldList.add(textRadialMirrorPosX);
textRadialMirrorPosY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 138, y, 62, 18);
textRadialMirrorPosY.setNumber(64);
textRadialMirrorPosY.setTooltip(Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
radialMirrorNumberFieldList.add(textRadialMirrorPosY);
textRadialMirrorPosZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textRadialMirrorPosZ.setNumber(0);
textRadialMirrorPosZ.setTooltip(Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
radialMirrorNumberFieldList.add(textRadialMirrorPosZ);
y = top + 47;
textRadialMirrorSlices = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 55, y, 50, 18);
textRadialMirrorSlices.setNumber(4);
textRadialMirrorSlices.setTooltip(Arrays.asList("The number of repeating slices.", TextFormatting.GRAY + "Minimally 2."));
radialMirrorNumberFieldList.add(textRadialMirrorSlices);
textRadialMirrorRadius = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textRadialMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textRadialMirrorRadius.setTooltip(Arrays.asList("How far the radial mirror reaches from its center position.",
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + ReachHelper.getMaxReach(mc.player) / 2,
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades."));
radialMirrorNumberFieldList.add(textRadialMirrorRadius);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS);
buttonCurrentPosition.setTooltip("Set radial mirror position to current player position");
radialMirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS);
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds"));
radialMirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS);
buttonDrawLines.setTooltip("Show lines");
radialMirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS);
buttonDrawPlanes.setTooltip("Show area");
radialMirrorIconButtonList.add(buttonDrawPlanes);
y = top + 76;
buttonRadialMirrorAlternate = new GuiCheckBox(id++, left + 140, y, " Alternate", false);
radialMirrorButtonList.add(buttonRadialMirrorAlternate);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (buildSettings != null) {
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
buttonRadialMirrorEnabled.setIsChecked(r.enabled);
textRadialMirrorPosX.setNumber(r.position.x);
textRadialMirrorPosY.setNumber(r.position.y);
textRadialMirrorPosZ.setNumber(r.position.z);
textRadialMirrorSlices.setNumber(r.slices);
buttonRadialMirrorAlternate.setIsChecked(r.alternate);
textRadialMirrorRadius.setNumber(r.radius);
drawLines = r.drawLines;
drawPlanes = r.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
if (textRadialMirrorPosX.getNumber() == Math.floor(textRadialMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds"));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to corner of block", "for even numbered builds"));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
}
buttonList.addAll(radialMirrorButtonList);
buttonList.addAll(radialMirrorIconButtonList);
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
return id;
}
@Override
public void updateScreen() {
super.updateScreen();
radialMirrorNumberFieldList.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;
buttonRadialMirrorEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonRadialMirrorEnabled.isChecked()) {
buttonRadialMirrorEnabled.y = yy;
fontRenderer.drawString("Radial 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);
textRadialMirrorPosX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF, true);
textRadialMirrorPosY.y = yy;
fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF, true);
textRadialMirrorPosZ.y = yy;
yy = y + 50;
fontRenderer.drawString("Slices", left + offset, yy + 2, 0xFFFFFF, true);
textRadialMirrorSlices.y = yy - 3;
fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF, true);
textRadialMirrorRadius.y = yy - 3;
yy = y + 72;
buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
yy = y + 76;
buttonRadialMirrorAlternate.y = yy;
radialMirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
radialMirrorIconButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
radialMirrorNumberFieldList
.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else {
buttonRadialMirrorEnabled.y = yy;
fontRenderer.drawString("Radial mirror disabled", left + offset, yy + 2, 0x999999, true);
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonRadialMirrorEnabled.isChecked())
{
radialMirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(scrollPane.parent, mouseX, mouseY));
radialMirrorNumberFieldList.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 : radialMirrorNumberFieldList) {
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);
radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideRadialMirrorEnabledLabel) {
buttonRadialMirrorEnabled.setIsChecked(!buttonRadialMirrorEnabled.isChecked());
buttonRadialMirrorEnabled.playPressSound(this.mc.getSoundHandler());
actionPerformed(buttonRadialMirrorEnabled);
}
return true;
}
@Override
public void actionPerformed(GuiButton button) {
super.actionPerformed(button);
if (button == buttonRadialMirrorEnabled) {
setCollapsed(!buttonRadialMirrorEnabled.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);
textRadialMirrorPosX.setNumber(pos.x);
textRadialMirrorPosY.setNumber(pos.y);
textRadialMirrorPosZ.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"));
textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5);
textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5);
textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber()));
textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber()));
textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.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");
}
radialMirrorNumberFieldList.forEach(numberField -> numberField.actionPerformed(button));
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked();
Vec3d radialMirrorPos = new Vec3d(0, 64, 0);
try {
radialMirrorPos = new Vec3d(textRadialMirrorPosX.getNumber(), textRadialMirrorPosY.getNumber(), textRadialMirrorPosZ
.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror position not a valid number.");
}
int radialMirrorSlices = 4;
try {
radialMirrorSlices = (int) textRadialMirrorSlices.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror slices not a valid number.");
}
boolean radialMirrorAlternate = buttonRadialMirrorAlternate.isChecked();
int radialMirrorRadius = 50;
try {
radialMirrorRadius = (int) textRadialMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
return new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPos, radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, drawLines, drawPlanes);
}
@Override
protected String getName() {
return "Radial mirror";
}
@Override
protected int getExpandedHeight() {
return 100;
}
}

View File

@@ -4,7 +4,6 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ClickType; import net.minecraft.inventory.ClickType;
import net.minecraft.inventory.Container; import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
@@ -46,9 +45,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 +66,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 +79,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 +92,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 +109,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

@@ -1,12 +1,12 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler; 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 +17,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 +31,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,51 @@
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 nl.requios.effortlessbuilding.*;
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.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
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 RadialMirrorSettingsGui radialMirrorSettingsGui;
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); radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
textMirrorPosZ.setText("0.5"); scrollPane.listEntries.add(radialMirrorSettingsGui);
mirrorTextFieldList.add(textMirrorPosZ);
y = top + 50; id = scrollPane.initGui(id, buttonList);
buttonMirrorX = new GuiCheckBox(id++, left + 60, y, " X", true);
mirrorButtonList.add(buttonMirrorX);
buttonMirrorY = new GuiCheckBox(id++, left + 100, y, " Y", false); //Close button
mirrorButtonList.add(buttonMirrorY); int y = height - 26;
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 +54,79 @@ 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(); RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
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);
buildSettings.setRadialMirrorSettings(r);
//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,15 @@
package nl.requios.effortlessbuilding.helper;
import com.google.gson.JsonObject;
import net.minecraftforge.common.crafting.IConditionFactory;
import net.minecraftforge.common.crafting.JsonContext;
import nl.requios.effortlessbuilding.BuildConfig;
import java.util.function.BooleanSupplier;
public class ReachConditionFactory implements IConditionFactory {
@Override
public BooleanSupplier parse(JsonContext context, JsonObject json) {
return () -> BuildConfig.reach.enableReachUpgrades;
}
}

View File

@@ -0,0 +1,27 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.entity.player.EntityPlayer;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
public class ReachHelper {
public static int getMaxReach(EntityPlayer player) {
if (player.isCreative()) return BuildConfig.reach.maxReachCreative;
if (!BuildConfig.reach.enableReachUpgrades) return BuildConfig.reach.maxReachLevel3;
//Check buildsettings for reachUpgrade
int reachUpgrade = BuildSettingsManager.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 boolean canBreakFar(EntityPlayer player) {
return player.isCreative() || BuildConfig.survivalBalancers.breakFar;
}
}

View File

@@ -0,0 +1,435 @@
package nl.requios.effortlessbuilding.helper;
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.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.*;
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 nl.requios.effortlessbuilding.proxy.ClientProxy;
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;
@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 Color colorRadial = 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());
beginLines();
//Mirror lines and areas
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, true);
}
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, true);
}
//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);
}
}
//Radial mirror lines and areas
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
if (r != null && r.enabled)
{
Vec3d pos = r.position.add(epsilon);
int radius = r.radius;
float angle = 2f * ((float) Math.PI) / r.slices;
Vec3d relStartVec = new Vec3d(radius, 0, 0);
if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f);
for (int i = 0; i < r.slices; i++) {
Vec3d relNewVec = relStartVec.rotateYaw(angle * i);
Vec3d newVec = pos.add(relNewVec);
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z);
drawMirrorPlane(posA, posB, colorRadial, r.drawLines, r.drawPlanes, false);
}
}
endLines();
//Render block previews
RayTraceResult lookingAt = ClientProxy.getLookingAt(player);
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK)
{
beginBlockPreviews();
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
BlockPos startPos = lookingAt.getBlockPos();
//Check if tool (or none) in hand
ItemStack mainhand = player.getHeldItemMainhand();
boolean toolInHand = !(!mainhand.isEmpty() && (mainhand.getItem() instanceof ItemBlock || mainhand.getItem() instanceof ItemRandomizerBag));
boolean replaceable =
player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!buildSettings.doQuickReplace() && !toolInHand && !replaceable) {
startPos = startPos.offset(lookingAt.sideHit);
}
//Get under tall grass and other replaceable blocks
if (buildSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down();
}
if (BuildModifiers.isEnabled(buildSettings, startPos) || BuildConfig.visuals.alwaysShowBlockPreview) {
//get coordinates
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startPos);
//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 = lookingAt.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, lookingAt.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, false, EnumFacing.UP, player) &&
SurvivalHelper.canReplace(player.world, player, blockPos)) {
renderBlockPreview(dispatcher, blockPos, blockState);
}
}
}
}
endBlockPreviews();
beginLines();
//Draw outlines if tool in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
if (toolInHand && breakingRaytrace != null && breakingRaytrace.typeOfHit == RayTraceResult.Type.BLOCK) {
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, breakingRaytrace.getBlockPos());
//Only render first outline if further than normal reach
boolean excludeFirst = objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK;
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i);
IBlockState blockState = player.world.getBlockState(coordinate);
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) {
if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) {
renderBlockOutline(coordinate);
}
}
}
}
endLines();
}
end();
}
//----Mirror----
public static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) {
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();
if (drawVerticalLines) {
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

@@ -0,0 +1,232 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Enchantments;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class SurvivalHelper {
//Used for all placing of blocks in this mod.
//Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack.
//Based on ItemBlock#onItemUse
public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState, ItemStack itemstack, EnumFacing facing, Vec3d hitVec, boolean skipCollisionCheck, boolean playSound) {
if (!world.isBlockLoaded(pos, true)) return false;
//Randomizer bag synergy
//Find itemstack that belongs to the blockstate
if (itemstack.getItem() == EffortlessBuilding.ITEM_RANDOMIZER_BAG) {
IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(itemstack);
itemstack = ItemRandomizerBag.findStack(bagInventory, Item.getItemFromBlock(blockState.getBlock()));
}
//Check if itemstack is correct
if (!(itemstack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemstack.getItem()) != blockState.getBlock()) {
EffortlessBuilding.log(player, "Cannot (re)place block", true);
EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemstack.toString() + " does not match blockstate " + blockState.toString());
return false;
}
Block block = ((ItemBlock) itemstack.getItem()).getBlock();
if (!itemstack.isEmpty() && canPlayerEdit(player, world, pos, itemstack) &&
mayPlace(world, block, blockState, pos, skipCollisionCheck, facing.getOpposite(), player) &&
canReplace(world, player, pos)) {
//Drop existing block
dropBlock(world, player, pos);
boolean placed = ((ItemBlock) itemstack.getItem()).placeBlockAt(itemstack, player, world, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, blockState);
if (!placed) return false;
//From ItemBlock#placeBlockAt
// if (!world.setBlockState(pos, blockState, 11)) return false;
//
IBlockState state = world.getBlockState(pos);
// if (state.getBlock() == block)
// {
// ((ItemBlock) itemstack.getItem()).setTileEntityNBT(world, player, pos, itemstack);
// block.onBlockPlacedBy(world, pos, state, player, itemstack);
//
//// if (player instanceof EntityPlayerMP)
//// CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP)player, pos, itemstack);
// }
if (playSound) {
SoundType soundtype = state.getBlock().getSoundType(state, world, pos, player);
world.playSound(null, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
}
if (!player.isCreative() && Block.getBlockFromItem(itemstack.getItem()) == block) {
itemstack.shrink(1);
}
return true;
}
return false;
}
//Used for all breaking of blocks in this mod.
//Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory
public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos) {
if (!world.isBlockLoaded(pos, false)) return false;
//Check if can break
if (canBreak(world, player, pos))
{
//Drop existing block
dropBlock(world, player, pos);
//Damage tool
player.getHeldItemMainhand().onBlockDestroyed(world, world.getBlockState(pos), pos, player);
world.setBlockToAir(pos);
return true;
}
return false;
}
//Can break using held tool? (or in creative)
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;
return canHarvestBlock(blockState.getBlock(), player, world, pos);
}
//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);
//Dont break bedrock
if (state.getBlockHardness((World) world, pos) < 0) {
return false;
}
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)
public static boolean canReplace(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return true;
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
if (state.getMaterial().isToolNotRequired()) return true;
return false;
}
//Gives items directly to player
public static void dropBlock(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return;
IBlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand());
// int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand());
// List<ItemStack> drops = blockState.getBlock().getDrops(world, pos, blockState, fortune);
// for (ItemStack drop : drops)
// {
// ItemHandlerHelper.giveItemToPlayer(player, drop);
// }
}
//From EntityPlayer#canPlayerEdit
public static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack)
{
if (player.capabilities.allowEdit)
{
//True in creative and survival mode
return true;
}
else
{
//Adventure mode
Block block = world.getBlockState(pos).getBlock();
return stack.canPlaceOn(block) || stack.canEditBlocks();
}
}
//From World#mayPlace
public static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
{
IBlockState iblockstate1 = world.getBlockState(pos);
AxisAlignedBB axisalignedbb = skipCollisionCheck ? Block.NULL_AABB : blockIn.getDefaultState().getCollisionBoundingBox(world, pos);
if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos)))
{
return false;
}
//Check if same block
//Necessary otherwise extra items will be dropped
if (iblockstate1 == newBlockState) {
return false;
}
if (iblockstate1.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL)
{
return true;
}
//Check quickreplace
if (placer instanceof EntityPlayer && BuildSettingsManager.getBuildSettings(((EntityPlayer) placer)).doQuickReplace()) {
return true;
}
return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
}
}

View File

@@ -13,34 +13,34 @@ import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.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 nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.Mirror;
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");
this.setUnlocalizedName(this.getRegistryName().toString()); this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1; this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.DECORATIONS); this.setCreativeTab(CreativeTabs.TOOLS);
} }
@Override @Override
@@ -59,11 +59,7 @@ public class ItemRandomizerBag extends Item {
if (bagInventory == null) if (bagInventory == null)
return EnumActionResult.FAIL; return EnumActionResult.FAIL;
int randomSlot = pickRandomSlot(bagInventory); ItemStack toPlace = pickRandomStack(bagInventory);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) return EnumActionResult.FAIL;
ItemStack toPlace = bagInventory.getStackInSlot(randomSlot);
if (toPlace.isEmpty()) return EnumActionResult.FAIL; if (toPlace.isEmpty()) return EnumActionResult.FAIL;
//Previously: use onItemUse to place block (no synergy) //Previously: use onItemUse to place block (no synergy)
@@ -76,42 +72,34 @@ public class ItemRandomizerBag extends Item {
IBlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(world, pos, facing, IBlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(world, pos, facing,
hitX, hitY, hitZ, toPlace.getMetadata(), player, hand); hitX, hitY, hitZ, toPlace.getMetadata(), player, hand);
world.setBlockState(pos, blockState);
//Synergy SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(hitX, hitY, hitZ), false, true);
BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, pos, blockState);
BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
Mirror.onBlockPlaced(placeEvent);
Array.onBlockPlaced(placeEvent);
} }
return EnumActionResult.SUCCESS; return EnumActionResult.SUCCESS;
} }
@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);
int randomSlot = pickRandomSlot(bagInventory); ItemStack toUse = pickRandomStack(bagInventory);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) if (toUse.isEmpty()) return new ActionResult<>(EnumActionResult.FAIL, bag);
return new ActionResult<>(EnumActionResult.FAIL, player.getHeldItem(hand));
ItemStack toUse = bagInventory.getStackInSlot(randomSlot);
if (toUse.isEmpty()) return new ActionResult<>(EnumActionResult.FAIL, player.getHeldItem(hand));
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);
} }
/** /**
@@ -131,7 +119,7 @@ public class ItemRandomizerBag extends Item {
* @param bagInventory * @param bagInventory
* @return * @return
*/ */
public static int pickRandomSlot(IItemHandler bagInventory) { public static ItemStack pickRandomStack(IItemHandler bagInventory) {
//Find how many stacks are non-empty, and save them in a list //Find how many stacks are non-empty, and save them in a list
int nonempty = 0; int nonempty = 0;
List<ItemStack> nonEmptyStacks = new ArrayList<>(INV_SIZE); List<ItemStack> nonEmptyStacks = new ArrayList<>(INV_SIZE);
@@ -148,12 +136,26 @@ public class ItemRandomizerBag extends Item {
if (nonEmptyStacks.size() != originalSlots.size()) if (nonEmptyStacks.size() != originalSlots.size())
throw new Error("NonEmptyStacks and OriginalSlots not same size"); throw new Error("NonEmptyStacks and OriginalSlots not same size");
if (nonempty == 0) return -1; if (nonempty == 0) return ItemStack.EMPTY;
//Pick random slot //Pick random slot
int randomSlot = rand.nextInt(nonempty); int randomSlot = rand.nextInt(nonempty);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
return originalSlots.get(randomSlot); int originalSlot = originalSlots.get(randomSlot);
if (originalSlot < 0 || originalSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
return bagInventory.getStackInSlot(originalSlot);
}
public static ItemStack findStack(IItemHandler bagInventory, Item item) {
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == item) {
return stack;
}
}
return ItemStack.EMPTY;
} }
@Override @Override
@@ -172,4 +174,18 @@ public class ItemRandomizerBag extends Item {
tooltip.add(TextFormatting.BLUE + "Rightclick" + TextFormatting.GRAY + " to place a random block"); tooltip.add(TextFormatting.BLUE + "Rightclick" + TextFormatting.GRAY + " to place a random block");
tooltip.add(TextFormatting.BLUE + "Sneak + rightclick" + TextFormatting.GRAY + " to open inventory"); tooltip.add(TextFormatting.BLUE + "Sneak + rightclick" + TextFormatting.GRAY + " to open inventory");
} }
@Override
public String getTranslationKey() {
return super.getTranslationKey();
}
public static void resetRandomness() {
rand.setSeed(currentSeed);
}
public static void renewRandomness() {
currentSeed = Calendar.getInstance().getTimeInMillis();
rand.setSeed(currentSeed);
}
} }

View File

@@ -0,0 +1,73 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade1 extends Item {
public ItemReachUpgrade1() {
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
int currentLevel = buildSettings.getReachUpgrade();
if (currentLevel == 0) {
buildSettings.setReachUpgrade(1);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 0) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
@Override
public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) {
EffortlessBuilding.log("used");
return ItemStack.EMPTY;
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel1);
}
@Override
public String getTranslationKey() {
return super.getTranslationKey();
}
}

View File

@@ -0,0 +1,71 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade2 extends Item {
public ItemReachUpgrade2() {
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
int currentLevel = buildSettings.getReachUpgrade();
if (currentLevel == 1) {
buildSettings.setReachUpgrade(2);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 1) {
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 1 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 1) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel2);
tooltip.add(TextFormatting.GRAY + "Previous upgrades need to be consumed first");
}
@Override
public String getTranslationKey() {
return super.getTranslationKey();
}
}

View File

@@ -0,0 +1,74 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade3 extends Item {
public ItemReachUpgrade3() {
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
int currentLevel = buildSettings.getReachUpgrade();
if (currentLevel == 2) {
buildSettings.setReachUpgrade(3);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 2) {
if (currentLevel == 0)
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 1 and 2 first.");
if (currentLevel == 1)
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 2 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 2) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel3);
tooltip.add(TextFormatting.GRAY + "Previous upgrades need to be consumed first");
}
@Override
public String getTranslationKey() {
return super.getTranslationKey();
}
}

View File

@@ -0,0 +1,91 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
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.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.BuildModifiers;
import nl.requios.effortlessbuilding.EffortlessBuilding;
public class BlockBrokenMessage implements IMessage {
private boolean blockHit;
private BlockPos blockPos;
private EnumFacing sideHit;
private Vec3d hitVec;
public BlockBrokenMessage() {
this.blockHit = false;
this.blockPos = BlockPos.ORIGIN;
this.sideHit = EnumFacing.UP;
this.hitVec = new Vec3d(0, 0, 0);
}
public BlockBrokenMessage(RayTraceResult result) {
this.blockHit = result.typeOfHit == RayTraceResult.Type.BLOCK;
this.blockPos = result.getBlockPos();
this.sideHit = result.sideHit;
this.hitVec = result.hitVec;
}
public boolean isBlockHit() {
return blockHit;
}
public BlockPos getBlockPos() {
return blockPos;
}
public EnumFacing getSideHit() {
return sideHit;
}
public Vec3d getHitVec() {
return hitVec;
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeBoolean(blockHit);
buf.writeInt(blockPos.getX());
buf.writeInt(blockPos.getY());
buf.writeInt(blockPos.getZ());
buf.writeInt(sideHit.getIndex());
buf.writeDouble(hitVec.x);
buf.writeDouble(hitVec.y);
buf.writeDouble(hitVec.z);
}
@Override
public void fromBytes(ByteBuf buf) {
blockHit = buf.readBoolean();
blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
sideHit = EnumFacing.byIndex(buf.readInt());
hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
}
// The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<BlockBrokenMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(BlockBrokenMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side");
if (ctx.side == Side.SERVER) {
//Received serverside
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
BuildModifiers.onBlockBrokenMessage(ctx.getServerHandler().player, message);
});
}
// No response packet
return null;
}
}
}

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,41 +57,39 @@ 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
public void fromBytes(ByteBuf buf) { public void fromBytes(ByteBuf buf) {
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.byIndex(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
return null;
} }
// No response packet
return null;
} }
} }
} }

View File

@@ -1,20 +1,15 @@
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;
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 nl.requios.effortlessbuilding.Array; import nl.requios.effortlessbuilding.*;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings; import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.Mirror;
public class BuildSettingsMessage implements IMessage { public class BuildSettingsMessage implements IMessage {
@@ -31,49 +26,96 @@ public class BuildSettingsMessage implements IMessage {
public void toBytes(ByteBuf buf) { public void toBytes(ByteBuf buf) {
//MIRROR //MIRROR
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
buf.writeBoolean(m.enabled); buf.writeBoolean(m != null);
buf.writeDouble(m.position.x); if (m != null) {
buf.writeDouble(m.position.y); buf.writeBoolean(m.enabled);
buf.writeDouble(m.position.z); buf.writeDouble(m.position.x);
buf.writeBoolean(m.mirrorX); buf.writeDouble(m.position.y);
buf.writeBoolean(m.mirrorY); buf.writeDouble(m.position.z);
buf.writeBoolean(m.mirrorZ); buf.writeBoolean(m.mirrorX);
buf.writeInt(m.radius); buf.writeBoolean(m.mirrorY);
buf.writeBoolean(m.drawLines); buf.writeBoolean(m.mirrorZ);
buf.writeBoolean(m.drawPlanes); buf.writeInt(m.radius);
buf.writeBoolean(m.drawLines);
buf.writeBoolean(m.drawPlanes);
}
//ARRAY //ARRAY
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = buildSettings.getArraySettings();
buf.writeBoolean(a.enabled); buf.writeBoolean(a != null);
buf.writeInt(a.offset.getX()); if (a != null) {
buf.writeInt(a.offset.getY()); buf.writeBoolean(a.enabled);
buf.writeInt(a.offset.getZ()); buf.writeInt(a.offset.getX());
buf.writeInt(a.count); buf.writeInt(a.offset.getY());
buf.writeInt(a.offset.getZ());
buf.writeInt(a.count);
}
buf.writeBoolean(buildSettings.doQuickReplace()); buf.writeBoolean(buildSettings.doQuickReplace());
buf.writeInt(buildSettings.getReachUpgrade());
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null);
if (r != null) {
buf.writeBoolean(r.enabled);
buf.writeDouble(r.position.x);
buf.writeDouble(r.position.y);
buf.writeDouble(r.position.z);
buf.writeInt(r.slices);
buf.writeBoolean(r.alternate);
buf.writeInt(r.radius);
buf.writeBoolean(r.drawLines);
buf.writeBoolean(r.drawPlanes);
}
} }
@Override @Override
public void fromBytes(ByteBuf buf) { public void fromBytes(ByteBuf buf) {
//MIRROR //MIRROR
boolean mirrorEnabled = buf.readBoolean(); Mirror.MirrorSettings m = new Mirror.MirrorSettings();
Vec3d mirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); if (buf.readBoolean()) {
boolean mirrorX = buf.readBoolean(); boolean mirrorEnabled = buf.readBoolean();
boolean mirrorY = buf.readBoolean(); Vec3d mirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean mirrorZ = buf.readBoolean(); boolean mirrorX = buf.readBoolean();
int mirrorRadius = buf.readInt(); boolean mirrorY = buf.readBoolean();
boolean mirrorDrawLines = buf.readBoolean(); boolean mirrorZ = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean(); int mirrorRadius = buf.readInt();
Mirror.MirrorSettings m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes); boolean mirrorDrawLines = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean();
m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius,
mirrorDrawLines, mirrorDrawPlanes);
}
//ARRAY //ARRAY
boolean arrayEnabled = buf.readBoolean(); Array.ArraySettings a = new Array.ArraySettings();
BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); if (buf.readBoolean()) {
int arrayCount = buf.readInt(); boolean arrayEnabled = buf.readBoolean();
Array.ArraySettings a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
int arrayCount = buf.readInt();
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();
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings();
if (buf.readBoolean()) {
boolean radialMirrorEnabled = buf.readBoolean();
Vec3d radialMirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
int radialMirrorSlices = buf.readInt();
boolean radialMirrorAlternate = buf.readBoolean();
int radialMirrorRadius = buf.readInt();
boolean radialMirrorDrawLines = buf.readBoolean();
boolean radialMirrorDrawPlanes = buf.readBoolean();
r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices,
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
}
buildSettings = new BuildSettings(m, a, r, quickReplace, reachUpgrade);
} }
// The params of the IMessageHandler are <REQ, REPLY> // The params of the IMessageHandler are <REQ, REPLY>
@@ -84,25 +126,18 @@ public class BuildSettingsMessage implements IMessage {
public IMessage onMessage(BuildSettingsMessage message, MessageContext ctx) { public IMessage onMessage(BuildSettingsMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side"); //EffortlessBuilding.log("message received on " + ctx.side + " side");
// This is the player the packet was sent to the server from
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
m.radius = Math.min(m.radius, Mirror.MAX_RADIUS);
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);
threadListener.addScheduledTask(() -> { threadListener.addScheduledTask(() -> {
EntityPlayer p = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
BuildSettingsManager.setBuildSettings(p, buildSettings);
// Sanitize
BuildSettingsManager.sanitize(buildSettings, player);
BuildSettingsManager.setBuildSettings(player, buildSettings);
}); });
// No response packet // No response packet
return null; return null;

View File

@@ -1,6 +1,8 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.block.Block; import net.minecraft.block.Block;
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;
@@ -8,23 +10,39 @@ import net.minecraft.client.settings.KeyBinding;
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.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.IThreadListener; import net.minecraft.util.IThreadListener;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
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.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent; import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent;
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.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.ReachHelper;
import nl.requios.effortlessbuilding.helper.RenderHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
@@ -33,6 +51,7 @@ public class ClientProxy implements IProxy {
public static KeyBinding[] keyBindings; public static KeyBinding[] keyBindings;
public static RayTraceResult previousLookAt; public static RayTraceResult previousLookAt;
public static RayTraceResult currentLookAt; public static RayTraceResult currentLookAt;
private static int breakCooldown = 0;
@Override @Override
public void preInit(FMLPreInitializationEvent event) { public void preInit(FMLPreInitializationEvent event) {
@@ -41,11 +60,12 @@ public class ClientProxy implements IProxy {
@Override @Override
public void init(FMLInitializationEvent event) { public void init(FMLInitializationEvent event) {
// register key bindings // register key bindings
keyBindings = new KeyBinding[2]; keyBindings = new KeyBinding[3];
// instantiate the key bindings // instantiate the key bindings
keyBindings[0] = new KeyBinding("key.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category"); keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category"); keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_F4, "key.effortlessbuilding.category");
// register all the key bindings // register all the key bindings
for (int i = 0; i < keyBindings.length; ++i) { for (int i = 0; i < keyBindings.length; ++i) {
@@ -70,7 +90,7 @@ public class ClientProxy implements IProxy {
@Override @Override
public void serverStarting(FMLServerStartingEvent event) { public void serverStarting(FMLServerStartingEvent event) {
// This will never get called on client side //This will get called clientside
} }
@SubscribeEvent @SubscribeEvent
@@ -84,27 +104,108 @@ public class ClientProxy implements IProxy {
} }
} }
@SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) @SubscribeEvent
public static void onKeyPress(InputEvent.KeyInputEvent event) { public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
// check each enumerated key binding type for pressed and take appropriate action if (event.getEntity() == Minecraft.getMinecraft().player) {
EntityPlayerSP player = Minecraft.getMinecraft().player; event.getWorld().addEventListener(new RenderHelper());
if (keyBindings[0].isPressed()) { }
// do stuff for this key binding here }
// remember you may need to send packet to server
if (Minecraft.getMinecraft().currentScreen == null) { @SubscribeEvent
Minecraft.getMinecraft().displayGuiScreen(new SettingsGui()); public static void onMouseInput(InputEvent.MouseInputEvent event) {
} else { Minecraft mc = Minecraft.getMinecraft();
player.closeScreen(); EntityPlayerSP player = mc.player;
if (!BuildModifiers.isEnabled(BuildSettingsManager.getBuildSettings(player), player.getPosition())) return;
if (mc.gameSettings.keyBindUseItem.isPressed()) {
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (currentItemStack.getItem() instanceof ItemBlock ||
(currentItemStack.getItem() instanceof ItemRandomizerBag && !player.isSneaking())) {
//find position in distance
RayTraceResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
EffortlessBuilding.packetHandler.sendToServer(new BlockPlacedMessage(lookingAt));
//play sound if further than normal
if ((lookingAt.hitVec.subtract(player.getPositionEyes(1f))).lengthSquared() > 25f) {
BlockPos blockPos = lookingAt.getBlockPos();
IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
player.world.playSound(player, blockPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS,
(soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
player.swingArm(EnumHand.MAIN_HAND);
}
}
} }
} }
if (mc.gameSettings.keyBindAttack.isKeyDown()) {
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindAttack.getKeyCode(), false);
//Break block in distance in creative (or survival if enabled in config)
if (ReachHelper.canBreakFar(player)) {
if (breakCooldown <= 0) {
breakCooldown = 6;
RayTraceResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
EffortlessBuilding.packetHandler.sendToServer(new BlockBrokenMessage(lookingAt));
//play sound
BlockPos blockPos = lookingAt.getBlockPos();
IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
player.world.playSound(player, blockPos, soundtype.getBreakSound(), SoundCategory.BLOCKS,
(soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
player.swingArm(EnumHand.MAIN_HAND);
}
} else {
breakCooldown--;
}
}
} else {
breakCooldown = 0;
}
event.setResult(Event.Result.ALLOW);
}
@SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true)
public static void onKeyPress(InputEvent.KeyInputEvent event) {
EntityPlayerSP player = Minecraft.getMinecraft().player;
//Remember to send packet to server if necessary
//Show HUD
if (keyBindings[0].isPressed()) {
//Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.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) {
Minecraft.getMinecraft().displayGuiScreen(new SettingsGui());
} else {
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 (player.isCreative()) {
player.sendChatMessage("/gamemode 0");
} else {
player.sendChatMessage("/gamemode 1");
}
}
} }
@SubscribeEvent @SubscribeEvent
@@ -112,6 +213,7 @@ public class ClientProxy implements IProxy {
if (event.phase != TickEvent.Phase.START) return; if (event.phase != TickEvent.Phase.START) return;
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) {
@@ -131,7 +233,18 @@ public class ClientProxy implements IProxy {
} }
} }
} }
}
public static RayTraceResult getLookingAt(EntityPlayer player) {
// World world = player.world;
//base distance off of player ability (config)
float raytraceRange = ReachHelper.getMaxReach(player) / 4f;
// 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 player.rayTrace(raytraceRange, 1f);
// 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
{ {
@@ -35,7 +30,6 @@ public class ServerProxy implements IProxy
@Override @Override
public void serverStarting(FMLServerStartingEvent event) public void serverStarting(FMLServerStartingEvent event)
{ {
//event.registerServerCommand(new CommandStructureCapture());
} }
@Override @Override

View File

@@ -1,5 +1,11 @@
key.effortlessbuilding.category=Effortless Building key.effortlessbuilding.category=Effortless Building
key.hud.desc=Open Settings key.effortlessbuilding.hud.desc=Open Settings
key.replace.desc=Switch Replace Mode key.effortlessbuilding.replace.desc=Toggle QuickReplace
key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode
item.effortlessbuilding:randomizer_bag.name=Randomizer Bag item.effortlessbuilding:randomizer_bag.name=Randomizer Bag
item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1
item.effortlessbuilding:reach_upgrade2.name=Reach Upgrade 2
item.effortlessbuilding:reach_upgrade3.name=Reach Upgrade 3
commands.reach.usage=/reach <level>

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "effortlessbuilding:items/reachupgrade1"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "effortlessbuilding:items/reachupgrade2"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "effortlessbuilding:items/reachupgrade3"
}
}

View File

@@ -0,0 +1,5 @@
{
"conditions": {
"enable_reach_upgrades": "nl.requios.effortlessbuilding.helper.ReachConditionFactory"
}
}

View File

@@ -0,0 +1,21 @@
{
"conditions": [{
"type": "effortlessbuilding:enable_reach_upgrades"
}],
"type": "minecraft:crafting_shaped",
"pattern": [
" S",
"/ "
],
"key": {
"S": {
"item": "minecraft:string"
},
"/": {
"item": "minecraft:stick"
}
},
"result": {
"item": "effortlessbuilding:reach_upgrade1"
}
}

View File

@@ -0,0 +1,21 @@
{
"conditions": [{
"type": "effortlessbuilding:enable_reach_upgrades"
}],
"type": "minecraft:crafting_shaped",
"pattern": [
" M",
"/ "
],
"key": {
"M": {
"item": "minecraft:magma_cream"
},
"/": {
"item": "minecraft:bone"
}
},
"result": {
"item": "effortlessbuilding:reach_upgrade2"
}
}

View File

@@ -0,0 +1,25 @@
{
"conditions": [{
"type": "effortlessbuilding:enable_reach_upgrades"
}],
"type": "minecraft:crafting_shaped",
"pattern": [
" FE",
" /F",
"/ "
],
"key": {
"E": {
"item": "minecraft:ender_eye"
},
"F": {
"item": "minecraft:feather"
},
"/": {
"item": "minecraft:blaze_rod"
}
},
"result": {
"item": "effortlessbuilding:reach_upgrade3"
}
}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

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",