19 Commits
1.0 ... 2.0

Author SHA1 Message Date
Christian Knaapen
2986b11983 Disabled shader reload key.
Disabled build modes when reach is 0.
Removed incomplete build mode icons.
Removed sound event (unused).
2019-02-18 20:29:52 +01:00
Christian Knaapen
be865d273c Breaking shows preview (breaking only in creative).
Build mode cancels when opposite mouse button is pressed (left button when placing, right button when breaking).
Simple shader when placing more than 1500 blocks (or when useShaders is false).
Added axis limits in addition to total block limit.
Fixed placing on self (and being pushed).
Fixed issue #15 silk touch, shearing leaves, dropping bed etc by using Block#harvestBlock (items dont drop directly to inventory anymore).
Fixed randomizerbag not randomizing in buildmodes.
2019-02-14 02:02:22 +01:00
Christian Knaapen
e1c23a5bec Fixed dissolve shader sometimes applying to wrong blocks (server and client are synced now, no more message to render).
Fixed build modes on server clicking twice.
Changing config ingame is now possible.
2019-02-12 16:06:54 +01:00
Christian Knaapen
a5e5e7240a Added Chisels and Bits compatibility (no double radial menu).
Added preliminary Architecturecraft compatibility (places right type, not rotation yet).
2019-02-11 17:23:57 +01:00
Christian Knaapen
1aa1401450 Moved radial menu to RenderHandler.
Resolved issue #12 and #13.
(And #10 with pull request.)
2019-02-10 19:27:53 +01:00
FenixFyreX
5944ea4aa1 Merged in FenixFyreX/effortless-building/block-proxy-compat (pull request #1)
Added compatibility for a few block proxies, like /dank/null.
2019-02-10 14:17:08 +00:00
FenixFyreX
0eda9baf8f Fixed sneaking being removed for randomizer bag in ClientProxy. 2019-02-08 11:13:48 -06:00
FenixFyreX
f36c5a4a5a Removed void tear, as it doesn't place items like I thought. 2019-02-08 10:56:02 -06:00
FenixFyreX
8f333249a3 Added compatibility for a few block proxies, like /dank/null. 2019-02-08 10:48:07 -06:00
FenixFyreX
c602f39059 Merged Requios/effortless-building into master 2019-02-08 01:32:43 -06:00
Christian Knaapen
009f385054 Added shader on placement. Added sound on drag (block placement sound).
Added line.
Highlight currently selected in radial menu (with colors).
Fixed scaling of icons.
Refactored RenderHandler into 3 classes and SurvivalHelper.
Added classes and icons for diagonal line, diagonal wall, slope floor and cube.
2019-02-08 03:26:41 +01:00
Christian Knaapen
73c55578e7 More shader stuff. Shader has world position through vertex shader and blockpos.
Dissolve from firstpos to secondpos with some randomness.
Blue pulse with diagonal highlights.
2019-02-07 00:09:12 +01:00
Christian Knaapen
e67849dd0b Messing with shader. 2019-02-06 19:56:37 +01:00
Christian Knaapen
7321d1af01 Updated forge.
Tweaked shader.
Cancel build mode with esc, e, leftclick.
Added breaking blocks with buildmodes.
2019-02-06 03:53:25 +01:00
Christian Knaapen
dfc2b11e94 Shader with dissolve and blue pulse on block previews.
Floor mode.
Block preview sorting based on player distance.
2019-02-06 00:09:11 +01:00
Christian Knaapen
ba82449632 Implemented BuildModes and Wall.
Renamed buildSettings to modifierSettings etc.
Added mode capability, message, settings.
Added icons for normal, normal+, line, wall and floor.
2019-02-05 02:30:23 +01:00
Christian Knaapen
ae4650ba35 Added radial menu with build modes.
Moved extended gui elements to own package.
2019-01-28 21:02:07 +01:00
Christian Knaapen
da0295538e Moved buildmodifier classes to buildmodifier package. 2019-01-28 17:23:13 +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
75 changed files with 3872 additions and 1011 deletions

View File

@@ -11,7 +11,7 @@ apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
version = "1.0" version = "1.12.2-2.0"
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,10 +29,14 @@ 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.
} }
repositories {
flatDir { dirs 'libs' }
}
dependencies { dependencies {
// you may put jars on which you depend on in ./libs // you may put jars on which you depend on in ./libs
// or you may define them like so.. // or you may define them like so..
@@ -50,6 +54,7 @@ dependencies {
// except that these dependencies get remapped to your current MCP mappings // except that these dependencies get remapped to your current MCP mappings
//deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev' //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
//deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev' //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
provided 'mod.chiselsandbits:chiselsandbits:14.30'
// for more info... // for more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html

Binary file not shown.

View File

@@ -50,13 +50,26 @@ public class BuildConfig {
"A percentage between 0% and 100%, where 0% is the same as disabling it,", "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.", "and 100% takes as much time as breaking each block individually.",
"The block in front of you always counts as 100%."}) "The block in front of you always counts as 100%."})
@RangeInt(min = 0, max = 100) @RangeInt(min = 0, max = 200)
public int miningTimePercentage = 50; public int miningTimePercentage = 50;
} }
public static class Visuals { public static class Visuals {
@Comment({"Show a block preview if you have a block in hand,", @Comment({"Show a block preview if you have a block in hand on build mode Normal"})
"even when mirror and array are off."})
public boolean alwaysShowBlockPreview = false; public boolean alwaysShowBlockPreview = false;
@Comment({"How long the dissolve effect takes when placing blocks.",
"Default between 30 and 60 ticks, you can multiply that here.",
"Recommended values:",
"Snappy: 0.7",
"Relaxing: 1.5"})
public double dissolveTimeMultiplier = 1.0;
@Comment({"Switch to using the simple performance shader when placing more than this many blocks."})
public int shaderTreshold = 1500;
@Comment({"Use fancy shaders while placing blocks"})
public boolean useShaders = true;
} }
} }

View File

@@ -1,207 +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.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, true, false);
}
}
}
public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
if (event.getWorld().isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own place event if anything is enabled
if (isEnabled(buildSettings, event.getPos())) {
//EffortlessBuilding.packetHandler.sendTo(new BlockPlacedMessage(), (EntityPlayerMP) event.getPlayer());
event.setCanceled(true);
}
}
//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) {
if (event.getWorld().isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own break event if anything is enabled
if (isEnabled(buildSettings, event.getPos())) {
//get coordinates
List<BlockPos> coordinates = findCoordinates(event.getPlayer(), event.getPos());
//break all those blocks
for (BlockPos coordinate : coordinates) {
if (event.getWorld().isBlockLoaded(coordinate, false)) {
SurvivalHelper.breakBlock(event.getWorld(), event.getPlayer(), coordinate);
}
}
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current block being placed too
coordinates.add(startPos);
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, startPos));
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

@@ -3,6 +3,8 @@ package nl.requios.effortlessbuilding;
import net.minecraft.block.Block; import net.minecraft.block.Block;
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.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
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.Config;
@@ -17,16 +19,17 @@ 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.BuildModifierCapabilityManager; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.command.CommandReach; import nl.requios.effortlessbuilding.command.CommandReach;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
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.ItemReachUpgrade1;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade2; import nl.requios.effortlessbuilding.item.ItemReachUpgrade2;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade3; import nl.requios.effortlessbuilding.item.ItemReachUpgrade3;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage; import nl.requios.effortlessbuilding.network.*;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.proxy.IProxy; import nl.requios.effortlessbuilding.proxy.IProxy;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -36,7 +39,7 @@ public class EffortlessBuilding
{ {
public static final String MODID = "effortlessbuilding"; public static final String MODID = "effortlessbuilding";
public static final String NAME = "Effortless Building"; public static final String NAME = "Effortless Building";
public static final String VERSION = "1.0"; public static final String VERSION = "1.12.2-2.0";
@Mod.Instance(EffortlessBuilding.MODID) @Mod.Instance(EffortlessBuilding.MODID)
public static EffortlessBuilding instance; public static EffortlessBuilding instance;
@@ -74,16 +77,23 @@ public class EffortlessBuilding
{ {
logger = event.getModLog(); logger = event.getModLog();
CapabilityManager.INSTANCE.register( CapabilityManager.INSTANCE.register(ModifierCapabilityManager.IModifierCapability.class, new ModifierCapabilityManager.Storage(), ModifierCapabilityManager.ModifierCapability.class);
BuildModifierCapabilityManager.IBuildModifierCapability.class, new BuildModifierCapabilityManager.Storage(), BuildModifierCapabilityManager.BuildModifierCapability.class); CapabilityManager.INSTANCE.register(ModeCapabilityManager.IModeCapability.class, new ModeCapabilityManager.Storage(), ModeCapabilityManager.ModeCapability.class);
EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(ModifierSettingsMessage.MessageHandler.class, ModifierSettingsMessage.class, 0, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.CLIENT); EffortlessBuilding.packetHandler.registerMessage(ModifierSettingsMessage.MessageHandler.class, ModifierSettingsMessage.class, 0, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 1, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(ModeSettingsMessage.MessageHandler.class, ModeSettingsMessage.class, 1, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 1, Side.CLIENT); EffortlessBuilding.packetHandler.registerMessage(ModeSettingsMessage.MessageHandler.class, ModeSettingsMessage.class, 1, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 2, Side.SERVER); EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 2, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 2, Side.CLIENT);
EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 3, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(CancelModeMessage.MessageHandler.class, CancelModeMessage.class, 4, Side.SERVER);
EffortlessBuilding.packetHandler.registerMessage(RequestLookAtMessage.MessageHandler.class, RequestLookAtMessage.class, 5, Side.CLIENT);
proxy.preInit(event); proxy.preInit(event);
} }
@@ -104,6 +114,7 @@ public class EffortlessBuilding
public void postInit(FMLPostInitializationEvent event) public void postInit(FMLPostInitializationEvent event)
{ {
proxy.postInit(event); proxy.postInit(event);
CompatHelper.postInit();
} }
@EventHandler @EventHandler

View File

@@ -4,9 +4,11 @@ import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.config.Config; import net.minecraftforge.common.config.Config;
@@ -18,8 +20,16 @@ import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent; import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
import java.util.List; import java.util.List;
@@ -47,12 +57,13 @@ 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 BuildModifierCapabilityManager.Provider()); event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "BuildModifier"), new ModifierCapabilityManager.Provider());
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "BuildMode"), new ModeCapabilityManager.Provider());
} }
} }
@SubscribeEvent @SubscribeEvent
public void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event) public static void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event)
{ {
if (event.getModID().equals(EffortlessBuilding.MODID)) if (event.getModID().equals(EffortlessBuilding.MODID))
{ {
@@ -66,14 +77,36 @@ public class EventHandler
// } // }
@SubscribeEvent @SubscribeEvent
//Only called serverside
public static void onBlockPlaced(BlockEvent.PlaceEvent event) { public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
//Still call it to cancel event //Cancel event if necessary
BuildModifiers.onBlockPlaced(event); EntityPlayer player = event.getPlayer();
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.Normal || modifierSettings.doQuickReplace()) {
event.setCanceled(true);
} else {
//Normal mode, let vanilla handle block placing
//But modifiers should still work
//Send message to client, which sends message back with raytrace info
EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(), (EntityPlayerMP) player);
}
} }
@SubscribeEvent @SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) { public static void onBlockBroken(BlockEvent.BreakEvent event) {
BuildModifiers.onBlockBroken(event); //Cancel event if necessary
//If cant break far then dont cancel event ever
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode();
if (buildMode != BuildModes.BuildModeEnum.Normal && ReachHelper.canBreakFar(event.getPlayer())) {
event.setCanceled(true);
} else {
//Normal mode, let vanilla handle block breaking
//But modifiers should still work
BuildModes.onBlockBroken(event);
}
} }
@SubscribeEvent @SubscribeEvent
@@ -88,6 +121,7 @@ public class EventHandler
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed())); //EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
float originalBlockHardness = event.getState().getBlockHardness(world, pos); float originalBlockHardness = event.getState().getBlockHardness(world, pos);
if (originalBlockHardness < 0) return; //Dont break bedrock
float totalBlockHardness = 0; float totalBlockHardness = 0;
//get coordinates //get coordinates
List<BlockPos> coordinates = BuildModifiers.findCoordinates(player, pos); List<BlockPos> coordinates = BuildModifiers.findCoordinates(player, pos);

View File

@@ -0,0 +1,172 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.event.world.BlockEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.*;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
public class BuildModes {
//Static variables are shared between client and server in singleplayer
//We need them separate
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingClient = new Hashtable<>();
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingServer = new Hashtable<>();
public enum BuildModeEnum {
Normal ("Normal", new Normal()),
NormalPlus ("Normal+", new NormalPlus()),
Line ("Line", new Line()),
Wall ("Wall", new Wall()),
Floor ("Floor", new Floor()),
DiagonalLine ("", new DiagonalLine()),
DiagonalWall ("", new DiagonalWall()),
SlopeFloor ("", new SlopeFloor()),
Cube ("", new Cube());
public String name;
public IBuildMode instance;
BuildModeEnum(String name, IBuildMode instance) {
this.name = name;
this.instance = instance;
}
}
//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) {
//Check if not in the middle of breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) {
//Cancel breaking
initializeMode(player);
return;
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode();
int maxReach = ReachHelper.getMaxReach(player);
BlockPos startPos = null;
if (message.isBlockHit() && message.getBlockPos() != null) {
startPos = message.getBlockPos();
//Offset in direction of sidehit if not quickreplace and not replaceable
boolean replaceable = player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!modifierSettings.doQuickReplace() && !replaceable) {
startPos = startPos.offset(message.getSideHit());
}
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && replaceable) {
startPos = startPos.down();
}
//Check if player reach does not exceed startpos
if (player.getPosition().distanceSq(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
}
//Even when no starting block is found, call buildmode instance
//We might want to place things in the air
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace());
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, false);
return;
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (coordinates.size() > limit) {
coordinates = coordinates.subList(0, limit);
}
EnumFacing sideHit = buildMode.instance.getSideHit(player);
if (sideHit == null) sideHit = message.getSideHit();
Vec3d hitVec = buildMode.instance.getHitVec(player);
if (hitVec == null) hitVec = message.getHitVec();
BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec);
//Only works when finishing a buildmode is equal to placing some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
}
//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() &&
!CompatHelper.chiselsAndBitsProxy.isHoldingChiselTool(EnumHand.MAIN_HAND)) {
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(player.world, blockPos, player.world.getBlockState(blockPos), player);
onBlockBroken(event);
}
}
public static void onBlockBroken(BlockEvent.BreakEvent event) {
EntityPlayer player = event.getPlayer();
BlockPos pos = event.getPos();
//Check if not in the middle of placing
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing
initializeMode(player);
return;
}
//get coordinates
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, pos, EnumFacing.UP, Vec3d.ZERO, true);
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, true);
return;
}
//let buildmodifiers break blocks
BuildModifiers.onBlockBroken(player, coordinates);
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos, boolean skipRaytrace) {
List<BlockPos> coordinates = new ArrayList<>();
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace));
return coordinates;
}
public static void initializeMode(EntityPlayer player) {
//Resetting mode, so not placing or breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player);
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
}
}

View File

@@ -0,0 +1,36 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.List;
public class Cube implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -0,0 +1,36 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.List;
public class DiagonalLine implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -0,0 +1,36 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.List;
public class DiagonalWall implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -0,0 +1,146 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public class Floor implements IBuildMode {
//In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click
Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
Dictionary<UUID, EnumFacing> sideHitTable = new Hashtable<>();
Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>();
@Override
public void initialize(EntityPlayer player) {
rightClickClientTable.put(player.getUniqueID(), 0);
rightClickServerTable.put(player.getUniqueID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
sideHitTable.put(player.getUniqueID(), EnumFacing.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO);
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place wall
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//try on z axis
double y = firstPos.getY();
//then x and z are
double x = (y - start.y) / look.y * look.x + start.x;
double z = (y - start.y) / look.y * look.z + start.z;
Vec3d yBound = new Vec3d(x, y, z);
//distance to player
double yDistSquared = yBound.subtract(start).lengthSquared();
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
//check if its not behind the player and its not too close and not too far
boolean yValid = yBound.subtract(start).dotProduct(look) > 0 &&
yDistSquared > 4 && yDistSquared < reach * reach;
//select the one that is closest to the player and is valid
Vec3d selected = null;
if (yValid) selected = yBound;
if (selected == null) return list;
//check if it doesnt go through blocks
if (!skipRaytrace) {
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false);
if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) {
//return empty list
return list;
}
}
BlockPos secondPos = new BlockPos(selected);
//Add whole wall
//Limit amount of blocks you can place per row
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
//check if whole row fits within limit
if (Math.abs(y1 - y2) < limit - list.size()) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(l, m, n));
}
}
}
}
}
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return sideHitTable.get(player.getUniqueID());
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return hitVecTable.get(player.getUniqueID());
}
}

View File

@@ -0,0 +1,25 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.List;
public interface IBuildMode {
//Fired when a player selects a buildmode and when it needs to initializeMode
void initialize(EntityPlayer player);
//Fired when a block would be placed
//Return a list of coordinates where you want to place blocks
List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace);
//Fired continuously for visualization purposes
List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace);
EnumFacing getSideHit(EntityPlayer player);
Vec3d getHitVec(EntityPlayer player);
}

View File

@@ -0,0 +1,222 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public class Line implements IBuildMode {
//In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click
Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
Dictionary<UUID, EnumFacing> sideHitTable = new Hashtable<>();
Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>();
@Override
public void initialize(EntityPlayer player) {
rightClickClientTable.put(player.getUniqueID(), 0);
rightClickServerTable.put(player.getUniqueID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
sideHitTable.put(player.getUniqueID(), EnumFacing.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO);
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place wall
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//try on x axis
double x = firstPos.getX();
//then y and z are
double y = (x - start.x) / look.x * look.y + start.y;
double z = (x - start.x) / look.x * look.z + start.z;
Vec3d xBound = new Vec3d(x, y, z);
Vec3d xBoundLine = toLongestLine(xBound, firstPos);
double xDistToLine = xBoundLine.subtract(xBound).lengthSquared();
//distance to player
double xDistSquared = xBound.subtract(start).lengthSquared();
//try on y axis
y = firstPos.getY();
//then x and z are
x = (y - start.y) / look.y * look.x + start.x;
z = (y - start.y) / look.y * look.z + start.z;
Vec3d yBound = new Vec3d(x, y, z);
Vec3d yBoundLine = toLongestLine(yBound, firstPos);
double yDistToLine = yBoundLine.subtract(yBound).lengthSquared();
//distance to player
double yDistSquared = yBound.subtract(start).lengthSquared();
//try on z axis
z = firstPos.getZ();
//then x and y are
x = (z - start.z) / look.z * look.x + start.x;
y = (z - start.z) / look.z * look.y + start.y;
Vec3d zBound = new Vec3d(x, y, z);
Vec3d zBoundLine = toLongestLine(zBound, firstPos);
double zDistToLine = zBoundLine.subtract(zBound).lengthSquared();
//distance to player
double zDistSquared = zBound.subtract(start).lengthSquared();
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
//check if its not behind the player and its not too close and not too far
boolean xValid = xBound.subtract(start).dotProduct(look) > 0 &&
xDistSquared > 4 && xDistSquared < reach * reach;
boolean yValid = yBound.subtract(start).dotProduct(look) > 0 &&
yDistSquared > 4 && yDistSquared < reach * reach;
boolean zValid = zBound.subtract(start).dotProduct(look) > 0 &&
zDistSquared > 4 && zDistSquared < reach * reach;
//select the one that is closest (from wall position to its line counterpart) and is valid
//TODO: if multiple are very close, choose closest to player
Vec3d selected = null;
double selectedDistToLine = 0;
if (xValid) {
selected = xBoundLine;
selectedDistToLine = xDistToLine;
} else if (yValid) {
selected = yBoundLine;
selectedDistToLine = yDistToLine;
} else if (zValid) {
selected = zBoundLine;
selectedDistToLine = yDistToLine;
}
if (yValid && yDistToLine < selectedDistToLine) selected = yBoundLine;
if (zValid && zDistToLine < selectedDistToLine) selected = zBoundLine;
if (selected == null) return list;
//check if it doesnt go through blocks
if (!skipRaytrace) {
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false);
if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) {
//return empty list
return list;
}
}
BlockPos secondPos = new BlockPos(selected);
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
//Add whole line
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
outerloop:
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
if (list.size() >= axisLimit) break outerloop;
list.add(new BlockPos(l, m, n));
}
}
}
}
return list;
}
//Make it into a line
//Select the axis that is longest
private Vec3d toLongestLine(Vec3d boundVec, BlockPos firstPos) {
BlockPos bound = new BlockPos(boundVec);
BlockPos firstToSecond = bound.subtract(firstPos);
firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ()));
int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ()));
if (longest == firstToSecond.getX()) {
return new Vec3d(bound.getX(), firstPos.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getY()) {
return new Vec3d(firstPos.getX(), bound.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getZ()) {
return new Vec3d(firstPos.getX(), firstPos.getY(), bound.getZ());
}
return null;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return sideHitTable.get(player.getUniqueID());
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return hitVecTable.get(player.getUniqueID());
}
}

View File

@@ -0,0 +1,106 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
@Mod.EventBusSubscriber
public class ModeSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null
public static ModeSettings getModeSettings(EntityPlayer player) {
if (player.hasCapability(ModeCapabilityManager.modeCapability, null)) {
ModeCapabilityManager.IModeCapability capability = player.getCapability(
ModeCapabilityManager.modeCapability, null);
if (capability.getModeData() == null) {
capability.setModeData(new ModeSettings());
}
return capability.getModeData();
}
throw new IllegalArgumentException("Player does not have modeCapability capability");
}
public static void setModeSettings(EntityPlayer player, ModeSettings modeSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildsettings, player is null");
return;
}
if (player.hasCapability(ModeCapabilityManager.modeCapability, null)) {
ModeCapabilityManager.IModeCapability capability = player.getCapability(
ModeCapabilityManager.modeCapability, null);
capability.setModeData(modeSettings);
//Initialize new mode
BuildModes.initializeMode(player);
} else {
EffortlessBuilding.log(player, "Saving buildsettings failed.");
}
}
public static String sanitize(ModeSettings modeSettings, EntityPlayer player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
//TODO sanitize
return error;
}
public static class ModeSettings {
private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.Normal;
public ModeSettings() {
}
public ModeSettings(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
public BuildModes.BuildModeEnum getBuildMode() {
return this.buildMode;
}
public void setBuildMode(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
}
@SubscribeEvent
public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
EntityPlayer player = event.player;
handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
EntityPlayer player = event.player;
handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
EntityPlayer player = event.player;
handleNewPlayer(player);
}
private static void handleNewPlayer(EntityPlayer player){
if (getModeSettings(player) == null) {
setModeSettings(player, new ModeSettings());
}
//Only on server
if (!player.world.isRemote) {
//Send to client
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player));
EffortlessBuilding.packetHandler.sendTo(msg, (EntityPlayerMP) player);
}
}
}

View File

@@ -0,0 +1,40 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.List;
public class Normal implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
list.add(blockPos);
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -0,0 +1,40 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.List;
public class NormalPlus implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
list.add(blockPos);
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -0,0 +1,36 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.List;
public class SlopeFloor implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>();
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -0,0 +1,179 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public class Wall implements IBuildMode {
//In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click
Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
Dictionary<UUID, EnumFacing> sideHitTable = new Hashtable<>();
Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>();
@Override
public void initialize(EntityPlayer player) {
rightClickClientTable.put(player.getUniqueID(), 0);
rightClickServerTable.put(player.getUniqueID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
sideHitTable.put(player.getUniqueID(), EnumFacing.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO);
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place wall
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//try on x axis
double x = firstPos.getX();
//then y and z are
double y = (x - start.x) / look.x * look.y + start.y;
double z = (x - start.x) / look.x * look.z + start.z;
Vec3d xBound = new Vec3d(x, y, z);
//distance to player
double xDistSquared = xBound.subtract(start).lengthSquared();
//angle to look
//double xAngle = xBound.subtract(new Vec3d(firstPos)).normalize().dotProduct(look);
//try on z axis
z = firstPos.getZ();
//then x and y are
x = (z - start.z) / look.z * look.x + start.x;
y = (z - start.z) / look.z * look.y + start.y;
Vec3d zBound = new Vec3d(x, y, z);
//distance to player
double zDistSquared = zBound.subtract(start).lengthSquared();
//angle to look
//double zAngle = zBound.subtract(new Vec3d(firstPos)).normalize().dotProduct(look);
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
//check if its not behind the player and its not too close and not too far
boolean xValid = xBound.subtract(start).dotProduct(look) > 0 &&
xDistSquared > 4 && xDistSquared < reach * reach;
boolean zValid = zBound.subtract(start).dotProduct(look) > 0 &&
zDistSquared > 4 && zDistSquared < reach * reach;
//select the one that is closest and is valid
Vec3d selected = null;
if (xValid)
selected = xBound;
else if (zValid)
selected = zBound;
if (zValid && zDistSquared < xDistSquared/*Math.abs(zAngle) < Math.abs(xAngle)*/) selected = zBound;
if (selected == null) return list;
//check if it doesnt go through blocks
if (!skipRaytrace) {
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false);
if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) {
//return empty list
return list;
}
}
BlockPos secondPos = new BlockPos(selected);
//Add whole wall
//Limit amount of blocks you can place per row
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
//limit axis
if (x2 - x1 > axisLimit) x2 = x1 + axisLimit;
if (x1 - x2 > axisLimit) x2 = x1 - axisLimit;
if (y2 - y1 > axisLimit) y2 = y1 + axisLimit;
if (y1 - y2 > axisLimit) y2 = y1 - axisLimit;
if (z2 - z1 > axisLimit) z2 = z1 + axisLimit;
if (z1 - z2 > axisLimit) z2 = z1 - axisLimit;
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
//check if whole row fits within limit
if (Math.abs(y1 - y2) < limit - list.size()) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(l, m, n));
}
}
}
}
}
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return sideHitTable.get(player.getUniqueID());
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return hitVecTable.get(player.getUniqueID());
}
}

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -45,7 +45,7 @@ public class Array {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//find arraysettings for the player //find arraysettings for the player
ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings(); ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates; if (!isEnabled(a)) return coordinates;
BlockPos pos = startPos; BlockPos pos = startPos;
@@ -63,7 +63,7 @@ public class Array {
List<IBlockState> blockStates = new ArrayList<>(); 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(player).getArraySettings(); ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return blockStates; if (!isEnabled(a)) return blockStates;
BlockPos pos = startPos; BlockPos pos = startPos;
@@ -81,7 +81,8 @@ public class Array {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
blockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND); blockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
} }
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, ) //blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )

View File

@@ -0,0 +1,188 @@
package nl.requios.effortlessbuilding.buildmodifier;
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 nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BuildModifiers {
//Called from BuildModes
public static void onBlockPlaced(EntityPlayer player, List<BlockPos> startCoordinates, EnumFacing sideHit, Vec3d hitVec) {
World world = player.world;
ItemRandomizerBag.renewRandomness();
//Format hitvec to 0.x
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, startCoordinates);
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
if (world.isRemote) {
BlockPreviewRenderer.onBlocksPlaced();
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 onBlockBroken(EntityPlayer player, List<BlockPos> posList) {
World world = player.world;
List<BlockPos> coordinates = findCoordinates(player, posList);
if (coordinates.isEmpty()) return;
if (world.isRemote) {
BlockPreviewRenderer.onBlocksBroken();
return;
}
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = world.getBlockState(posList.get(0)).getBlockHardness(world, posList.get(0)) == 0f;
//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, player, coordinate);
}
}
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, List<BlockPos> posList) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current blocks being placed too
coordinates.addAll(posList);
//Find mirror/array/radial mirror coordinates for each blockpos
for (BlockPos blockPos : posList) {
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, blockPos));
coordinates.addAll(RadialMirror.findCoordinates(player, blockPos));
//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<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) {
return findCoordinates(player, new ArrayList<>(Arrays.asList(blockPos)));
}
public static List<IBlockState> findBlockStates(EntityPlayer player, List<BlockPos> posList, 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() || !CompatHelper.isItemBlockProxy(itemStack)) {
itemStack = player.getHeldItem(EnumHand.OFF_HAND);
}
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
return blockStates;
}
//Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack;
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
ItemRandomizerBag.resetRandomness();
//Add blocks in posList first
for (BlockPos blockPos : posList) {
if (!(itemStack.getItem() instanceof ItemBlock)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
blockStates.add(blockState);
itemStacks.add(itemBlock);
}
for (BlockPos blockPos : posList) {
IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
List<IBlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks);
blockStates.addAll(arrayBlockStates);
blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
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(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) {
return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(modifierSettings.getArraySettings()) ||
RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) ||
modifierSettings.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

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.BlockDirectional; import net.minecraft.block.BlockDirectional;
import net.minecraft.block.BlockDispenser; import net.minecraft.block.BlockDispenser;
@@ -23,7 +23,7 @@ public class Mirror {
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 = 10;
public boolean drawLines = true, drawPlanes = true; public boolean drawLines = true, drawPlanes = true;
public MirrorSettings() { public MirrorSettings() {
@@ -41,7 +41,7 @@ public class Mirror {
} }
public int getReach() { public int getReach() {
return radius * 2; return radius * 2; //Change ModifierSettings#setReachUpgrade too
} }
} }
@@ -49,7 +49,7 @@ public class Mirror {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//find mirrorsettings for the player //find mirrorsettings for the player
MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings(); MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return coordinates; if (!isEnabled(m, startPos)) return coordinates;
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates); if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
@@ -89,7 +89,7 @@ public class Mirror {
List<IBlockState> blockStates = new ArrayList<>(); List<IBlockState> blockStates = new ArrayList<>();
//find mirrorsettings for the player //find mirrorsettings for the player
MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings(); MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates; if (!isEnabled(m, startPos)) return blockStates;
//Randomizer bag synergy //Randomizer bag synergy

View File

@@ -1,51 +1,53 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding.buildmodifier;
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.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.BuildModifierCapabilityManager; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class BuildSettingsManager { public class ModifierSettingsManager {
//Retrieves the buildsettings of a player through the buildModifierCapability capability //Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null //Never returns null
public static BuildSettings getBuildSettings(EntityPlayer player){ public static ModifierSettings getModifierSettings(EntityPlayer player){
if (player.hasCapability(BuildModifierCapabilityManager.buildModifierCapability, null)) { if (player.hasCapability(ModifierCapabilityManager.modifierCapability, null)) {
BuildModifierCapabilityManager.IBuildModifierCapability capability = player.getCapability( ModifierCapabilityManager.IModifierCapability capability = player.getCapability(
BuildModifierCapabilityManager.buildModifierCapability, null); ModifierCapabilityManager.modifierCapability, null);
if (capability.getBuildModifierData() == null) { if (capability.getModifierData() == null) {
capability.setBuildModifierData(new BuildSettings()); capability.setModifierData(new ModifierSettings());
} }
return capability.getBuildModifierData(); return capability.getModifierData();
} }
throw new IllegalArgumentException("Player does not have buildModifierCapability capability"); throw new IllegalArgumentException("Player does not have modifierCapability capability");
} }
public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) { public static void setModifierSettings(EntityPlayer player, ModifierSettings modifierSettings) {
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(BuildModifierCapabilityManager.buildModifierCapability, null)) { if (player.hasCapability(ModifierCapabilityManager.modifierCapability, null)) {
BuildModifierCapabilityManager.IBuildModifierCapability capability = player.getCapability( ModifierCapabilityManager.IModifierCapability capability = player.getCapability(
BuildModifierCapabilityManager.buildModifierCapability, null); ModifierCapabilityManager.modifierCapability, null);
capability.setBuildModifierData(buildSettings); capability.setModifierData(modifierSettings);
} else { } else {
EffortlessBuilding.log(player, "Saving buildsettings failed."); EffortlessBuilding.log(player, "Saving buildsettings failed.");
} }
} }
public static String sanitize(BuildSettings buildSettings, EntityPlayer player) { public static String sanitize(ModifierSettings modifierSettings, EntityPlayer player) {
int maxReach = ReachHelper.getMaxReach(player); int maxReach = ReachHelper.getMaxReach(player);
String error = ""; String error = "";
//Mirror settings //Mirror settings
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m.radius < 1) { if (m.radius < 1) {
m.radius = 1; m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. "; error += "Mirror size has to be at least 1. This has been corrected. ";
@@ -56,7 +58,7 @@ public class BuildSettingsManager {
} }
//Array settings //Array settings
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = modifierSettings.getArraySettings();
if (a.count < 0) { if (a.count < 0) {
a.count = 0; a.count = 0;
error += "Array count may not be negative. It has been reset to 0."; error += "Array count may not be negative. It has been reset to 0.";
@@ -68,7 +70,7 @@ public class BuildSettingsManager {
} }
//Radial mirror settings //Radial mirror settings
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r.slices < 2) { if (r.slices < 2) {
r.slices = 2; r.slices = 2;
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2."; error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
@@ -84,30 +86,31 @@ public class BuildSettingsManager {
} }
//Other //Other
if (buildSettings.reachUpgrade < 0) { if (modifierSettings.reachUpgrade < 0) {
buildSettings.reachUpgrade = 0; modifierSettings.reachUpgrade = 0;
} }
if (buildSettings.reachUpgrade > 3) { if (modifierSettings.reachUpgrade > 3) {
buildSettings.reachUpgrade = 3; modifierSettings.reachUpgrade = 3;
} }
return error; return error;
} }
public static class BuildSettings { public static class ModifierSettings {
private Mirror.MirrorSettings mirrorSettings; private Mirror.MirrorSettings mirrorSettings;
private Array.ArraySettings arraySettings; private Array.ArraySettings arraySettings;
private RadialMirror.RadialMirrorSettings radialMirrorSettings; private RadialMirror.RadialMirrorSettings radialMirrorSettings;
private boolean quickReplace = false; private boolean quickReplace = false;
private int reachUpgrade = 0; private int reachUpgrade = 0;
public BuildSettings() { public ModifierSettings() {
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, public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) { RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
this.mirrorSettings = mirrorSettings; this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings; this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings; this.radialMirrorSettings = radialMirrorSettings;
@@ -116,26 +119,32 @@ public class BuildSettingsManager {
} }
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() { public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
return radialMirrorSettings; if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
return this.radialMirrorSettings;
} }
public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) { public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) {
if (radialMirrorSettings == null) return;
this.radialMirrorSettings = radialMirrorSettings; this.radialMirrorSettings = radialMirrorSettings;
} }
@@ -153,6 +162,20 @@ public class BuildSettingsManager {
public void setReachUpgrade(int reachUpgrade) { public void setReachUpgrade(int reachUpgrade) {
this.reachUpgrade = reachUpgrade; this.reachUpgrade = reachUpgrade;
//Set mirror radius to max
int reach = 10;
switch (reachUpgrade) {
case 0: reach = BuildConfig.reach.maxReachLevel0; break;
case 1: reach = BuildConfig.reach.maxReachLevel1; break;
case 2: reach = BuildConfig.reach.maxReachLevel2; break;
case 3: reach = BuildConfig.reach.maxReachLevel3; break;
}
if (this.mirrorSettings != null)
this.mirrorSettings.radius = reach / 2;
if (this.radialMirrorSettings != null)
this.radialMirrorSettings.radius = reach / 2;
} }
} }
@@ -168,15 +191,21 @@ 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 (getModifierSettings(player) == null) {
setBuildSettings(player, new BuildSettings()); setModifierSettings(player, new ModifierSettings());
} }
//Only on server //Only on server
if (!player.world.isRemote) { if (!player.world.isRemote) {
//Send to client //Send to client
BuildSettingsMessage msg = new BuildSettingsMessage(getBuildSettings(player)); ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player));
EffortlessBuilding.packetHandler.sendTo(msg, (EntityPlayerMP) player); EffortlessBuilding.packetHandler.sendTo(msg, (EntityPlayerMP) player);
} }
} }

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -48,7 +48,7 @@ public class RadialMirror {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//find radial mirror settings for the player //find radial mirror settings for the player
RadialMirrorSettings r = BuildSettingsManager.getBuildSettings(player).getRadialMirrorSettings(); RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return coordinates; if (!isEnabled(r, startPos)) return coordinates;
//get angle between slices //get angle between slices
@@ -82,7 +82,7 @@ public class RadialMirror {
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//find radial mirror settings for the player that placed the block //find radial mirror settings for the player that placed the block
RadialMirrorSettings r = BuildSettingsManager.getBuildSettings(player).getRadialMirrorSettings(); RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return blockStates; if (!isEnabled(r, startPos)) return blockStates;
@@ -123,7 +123,8 @@ public class RadialMirror {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
newBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND); newBlockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState); newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState);
} }

View File

@@ -0,0 +1,106 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.*;
@Mod.EventBusSubscriber
public class ModeCapabilityManager {
@CapabilityInject(IModeCapability.class)
public final static Capability<IModeCapability> modeCapability = null;
public interface IModeCapability {
ModeSettings getModeData();
void setModeData(ModeSettings modeSettings);
}
public static class ModeCapability implements IModeCapability {
private ModeSettings modeSettings;
@Override
public ModeSettings getModeData() {
return modeSettings;
}
@Override
public void setModeData(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
}
public static class Storage implements Capability.IStorage<IModeCapability> {
@Override
public NBTBase writeNBT(Capability<IModeCapability> capability, IModeCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound();
ModeSettings modeSettings = instance.getModeData();
if (modeSettings == null) modeSettings = new ModeSettings();
//compound.setInteger("buildMode", modeSettings.getBuildMode().ordinal());
//TODO add mode settings
return compound;
}
@Override
public void readNBT(Capability<IModeCapability> capability, IModeCapability instance, EnumFacing side, NBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt;
//BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")];
//TODO add mode settings
ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.Normal);
instance.setModeData(modeSettings);
}
}
public static class Provider implements ICapabilitySerializable<NBTBase> {
IModeCapability inst = modeCapability.getDefaultInstance();
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
return capability == modeCapability;
}
@Override
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
if (capability == modeCapability) return modeCapability.<T>cast(inst);
return null;
}
@Override
public NBTBase serializeNBT() {
return modeCapability.getStorage().writeNBT(modeCapability, inst, null);
}
@Override
public void deserializeNBT(NBTBase nbt) {
modeCapability.getStorage().readNBT(modeCapability, inst, null, nbt);
}
}
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
IModeCapability original = event.getOriginal().getCapability(modeCapability, null);
IModeCapability clone = event.getEntity().getCapability(modeCapability, null);
clone.setModeData(original.getModeData());
}
}

View File

@@ -11,49 +11,50 @@ import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
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.Array; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.Mirror; import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.RadialMirror;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.*;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class BuildModifierCapabilityManager { public class ModifierCapabilityManager {
@CapabilityInject(IBuildModifierCapability.class) @CapabilityInject(IModifierCapability.class)
public final static Capability<IBuildModifierCapability> buildModifierCapability = null; public final static Capability<IModifierCapability> modifierCapability = null;
public interface IBuildModifierCapability { public interface IModifierCapability {
BuildSettings getBuildModifierData(); ModifierSettings getModifierData();
void setBuildModifierData(BuildSettings buildSettings); void setModifierData(ModifierSettings modifierSettings);
} }
public static class BuildModifierCapability implements IBuildModifierCapability { public static class ModifierCapability implements IModifierCapability {
private BuildSettings buildSettings; private ModifierSettings modifierSettings;
@Override @Override
public BuildSettings getBuildModifierData() { public ModifierSettings getModifierData() {
return buildSettings; return modifierSettings;
} }
@Override @Override
public void setBuildModifierData(BuildSettings buildSettings) { public void setModifierData(ModifierSettings modifierSettings) {
this.buildSettings = buildSettings; this.modifierSettings = modifierSettings;
} }
} }
public static class Storage implements Capability.IStorage<IBuildModifierCapability> { public static class Storage implements Capability.IStorage<IModifierCapability> {
@Override @Override
public NBTBase writeNBT(Capability<IBuildModifierCapability> capability, IBuildModifierCapability instance, EnumFacing side) { public NBTBase writeNBT(Capability<IModifierCapability> capability, IModifierCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound(); NBTTagCompound compound = new NBTTagCompound();
BuildSettings buildSettings = instance.getBuildModifierData(); ModifierSettings modifierSettings = instance.getModifierData();
if (buildSettings == null) buildSettings = new BuildSettings(); if (modifierSettings == null) modifierSettings = new ModifierSettings();
//MIRROR //MIRROR
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings(); 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);
@@ -67,7 +68,7 @@ public class BuildModifierCapabilityManager {
compound.setBoolean("mirrorDrawPlanes", m.drawPlanes); compound.setBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY //ARRAY
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = modifierSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings(); 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());
@@ -75,12 +76,12 @@ public class BuildModifierCapabilityManager {
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.setInteger("reachUpgrade", modifierSettings.getReachUpgrade());
//compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace //compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
//RADIAL MIRROR //RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings(); if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.setBoolean("radialMirrorEnabled", r.enabled); compound.setBoolean("radialMirrorEnabled", r.enabled);
compound.setDouble("radialMirrorPosX", r.position.x); compound.setDouble("radialMirrorPosX", r.position.x);
@@ -96,7 +97,7 @@ public class BuildModifierCapabilityManager {
} }
@Override @Override
public void readNBT(Capability<IBuildModifierCapability> capability, IBuildModifierCapability instance, EnumFacing side, NBTBase nbt) { public void readNBT(Capability<IModifierCapability> capability, IModifierCapability instance, EnumFacing side, NBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt; NBTTagCompound compound = (NBTTagCompound) nbt;
//MIRROR //MIRROR
@@ -131,41 +132,42 @@ public class BuildModifierCapabilityManager {
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes); radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
BuildSettings buildSettings = new BuildSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade); ModifierSettings
instance.setBuildModifierData(buildSettings); modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
instance.setModifierData(modifierSettings);
} }
} }
public static class Provider implements ICapabilitySerializable<NBTBase> { public static class Provider implements ICapabilitySerializable<NBTBase> {
IBuildModifierCapability inst = buildModifierCapability.getDefaultInstance(); IModifierCapability inst = modifierCapability.getDefaultInstance();
@Override @Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) { public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
return capability == buildModifierCapability; return capability == modifierCapability;
} }
@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 == buildModifierCapability) return buildModifierCapability.<T>cast(inst); if (capability == modifierCapability) return modifierCapability.<T>cast(inst);
return null; return null;
} }
@Override @Override
public NBTBase serializeNBT() { public NBTBase serializeNBT() {
return buildModifierCapability.getStorage().writeNBT(buildModifierCapability, inst, null); return modifierCapability.getStorage().writeNBT(modifierCapability, inst, null);
} }
@Override @Override
public void deserializeNBT(NBTBase nbt) { public void deserializeNBT(NBTBase nbt) {
buildModifierCapability.getStorage().readNBT(buildModifierCapability, inst, null, nbt); modifierCapability.getStorage().readNBT(modifierCapability, 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) {
IBuildModifierCapability original = event.getOriginal().getCapability(buildModifierCapability, null); IModifierCapability original = event.getOriginal().getCapability(modifierCapability, null);
IBuildModifierCapability clone = event.getEntity().getCapability(buildModifierCapability, null); IModifierCapability clone = event.getEntity().getCapability(modifierCapability, null);
clone.setBuildModifierData(original.getBuildModifierData()); clone.setModifierData(original.getModifierData());
} }
} }

View File

@@ -7,9 +7,9 @@ import net.minecraft.command.WrongUsageException;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
public class CommandReach extends CommandBase { public class CommandReach extends CommandBase {
@Override @Override
@@ -24,20 +24,23 @@ public class CommandReach extends CommandBase {
@Override @Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
EntityPlayerMP player = (EntityPlayerMP) sender;
if (args.length != 1) { if (args.length != 1) {
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
EffortlessBuilding.log(player, "Current reach: level "+reachUpgrade);
throw new WrongUsageException("commands.reach.usage"); throw new WrongUsageException("commands.reach.usage");
} }
if (sender instanceof EntityPlayerMP) { if (sender instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) sender;
//Set reach level to args[0] //Set reach level to args[0]
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
buildSettings.setReachUpgrade(Integer.valueOf(args[0])); modifierSettings.setReachUpgrade(Integer.valueOf(args[0]));
BuildSettingsManager.setBuildSettings(player, buildSettings); ModifierSettingsManager.setModifierSettings(player, modifierSettings);
//Send to client //Send to client
EffortlessBuilding.packetHandler.sendTo(new BuildSettingsMessage(buildSettings), player); EffortlessBuilding.packetHandler.sendTo(new ModifierSettingsMessage(modifierSettings), player);
sender.sendMessage(new TextComponentString("Reach level of " + sender.getName() + " set to " + buildSettings.getReachUpgrade())); sender.sendMessage(new TextComponentString("Reach level of " + sender.getName() + " set to " + modifierSettings
.getReachUpgrade()));
} }
} }
} }

View File

@@ -0,0 +1,13 @@
package nl.requios.effortlessbuilding.compatibility;
import mod.chiselsandbits.core.ClientSide;
import mod.chiselsandbits.helpers.ChiselToolType;
import net.minecraft.util.EnumHand;
public class ActiveChiselsAndBitsProxy implements IChiselsAndBitsProxy {
@Override
public boolean isHoldingChiselTool(EnumHand hand) {
ChiselToolType toolType = ClientSide.instance.getHeldToolType(hand);
return toolType != null && toolType.hasMenu();
}
}

View File

@@ -0,0 +1,98 @@
package nl.requios.effortlessbuilding.compatibility;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
public class CompatHelper {
// Get a handle to the dank null item instance. This will remain null if the mod doesn't load
// and all checks will fail, so it works.
@GameRegistry.ObjectHolder("danknull:dank_null")
public static final Item dankNullItem = null;
public static IChiselsAndBitsProxy chiselsAndBitsProxy;
public static void postInit() {
if (Loader.isModLoaded("chiselsandbits")) {
// reflection to avoid hard dependency
try {
chiselsAndBitsProxy = Class.forName("nl.requios.effortlessbuilding.compatibility.ActiveChiselsAndBitsProxy").asSubclass(ActiveChiselsAndBitsProxy.class).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
} else {
chiselsAndBitsProxy = new DummyChiselsAndBitsProxy();
}
}
// Check if the item given is a proxy for blocks. For now, we check for the randomizer bag,
// /dank/null, or plain old blocks.
public static boolean isItemBlockProxy(ItemStack stack) {
Item item = stack.getItem();
if(item instanceof ItemBlock)
return true;
if((item instanceof ItemRandomizerBag))
return true;
if(item == dankNullItem)
return true;
return false;
}
// Get the block to be placed by this proxy. For the /dank/null, it's the slot stack
// pointed to by nbt integer selectedIndex.
public static ItemStack getItemBlockFromStack(ItemStack stack) {
Item item = stack.getItem();
if(item instanceof ItemRandomizerBag) {
return ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(stack));
} else if(item == dankNullItem) {
int index = 0;
if(stack.hasTagCompound() && stack.getTagCompound().hasKey("selectedIndex"))
index = stack.getTagCompound().getInteger("selectedIndex");
return stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
}
return ItemStack.EMPTY;
}
public static ItemStack getItemBlockByState(ItemStack stack, IBlockState state) {
Item blockItem = Item.getItemFromBlock(state.getBlock());
if(stack.getItem() instanceof ItemBlock)
return stack;
else if(stack.getItem() instanceof ItemRandomizerBag) {
IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(stack);
return ItemRandomizerBag.findStack(bagInventory, blockItem);
} else if(stack.getItem() == dankNullItem) {
int index = itemHandlerSlotForItem(stack, blockItem);
if(index >= 0)
return stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
}
return ItemStack.EMPTY;
}
// Handle IItemHandler slot stacks not being modifiable. We must call IItemHandler#extractItem,
// because the ItemStack returned by IItemHandler#getStackInSlot isn't modifiable.
public static void shrinkStack(ItemStack origStack, ItemStack curStack) {
if(origStack.getItem() == dankNullItem) {
int index = itemHandlerSlotForItem(origStack, curStack.getItem());
origStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).extractItem(index, 1, false);
} else
curStack.shrink(1);
}
private static int itemHandlerSlotForItem(ItemStack stack, Item blockItem) {
IItemHandler handler = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
for(int i = 0; i < handler.getSlots(); i++) {
ItemStack ref = handler.getStackInSlot(i);
if(ref.getItem() instanceof ItemBlock)
if(ref.getItem() == blockItem)
return i;
}
return -1;
}
}

View File

@@ -0,0 +1,10 @@
package nl.requios.effortlessbuilding.compatibility;
import net.minecraft.util.EnumHand;
public class DummyChiselsAndBitsProxy implements IChiselsAndBitsProxy {
@Override
public boolean isHoldingChiselTool(EnumHand hand) {
return false;
}
}

View File

@@ -0,0 +1,7 @@
package nl.requios.effortlessbuilding.compatibility;
import net.minecraft.util.EnumHand;
public interface IChiselsAndBitsProxy {
boolean isHoldingChiselTool(EnumHand hand);
}

View File

@@ -12,7 +12,7 @@ import nl.requios.effortlessbuilding.EffortlessBuilding;
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
public class RandomizerBagGuiContainer extends GuiContainer { public class RandomizerBagGuiContainer extends GuiContainer {
private static final ResourceLocation guiTextures = private static final ResourceLocation guiTextures =
new ResourceLocation(EffortlessBuilding.MODID + ":textures/gui/container/randomizerbag.png"); new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png");
private final InventoryPlayer inventoryPlayer; private final InventoryPlayer inventoryPlayer;
private final IItemHandler inventoryBag; private final IItemHandler inventoryBag;

View File

@@ -0,0 +1,400 @@
package nl.requios.effortlessbuilding.gui.buildmode;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.GL11;
import com.google.common.base.Stopwatch;
import net.minecraft.client.Minecraft;
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.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.ModelLoader;
import static nl.requios.effortlessbuilding.buildmode.BuildModes.*;
/**
* From Chisels and Bits by AlgorithmX2
* https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/client/gui/ChiselsAndBitsMenu.java
*/
public class RadialMenu extends GuiScreen {
private final float TIME_SCALE = 0.01f;
public static final RadialMenu instance = new RadialMenu();
private float visibility = 0.0f;
private Stopwatch lastChange = Stopwatch.createStarted();
public BuildModeEnum switchTo = null;
//public ButtonAction doAction = null;
public boolean actionUsed = false;
private float clampVis(final float f) {
return Math.max( 0.0f, Math.min( 1.0f, f ) );
}
public void raiseVisibility() {
visibility = clampVis( visibility + lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE );
lastChange = Stopwatch.createStarted();
}
public void decreaseVisibility() {
visibility = clampVis( visibility - lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE );
lastChange = Stopwatch.createStarted();
}
public boolean isVisible() {
return visibility > 0.001;
}
public void configure(final int scaledWidth, final int scaledHeight ) {
mc = Minecraft.getMinecraft();
fontRenderer = mc.fontRenderer;
width = scaledWidth;
height = scaledHeight;
}
private static class MenuButton {
public double x1, x2;
public double y1, y2;
public boolean highlighted;
//public final ButtonAction action;
public TextureAtlasSprite icon;
public int color;
public String name;
public EnumFacing textSide;
public MenuButton(final String name, /*final ButtonAction action,*/ final double x, final double y,
final TextureAtlasSprite ico, final EnumFacing textSide) {
this.name = name;
//this.action = action;
x1 = x;
x2 = x + 18;
y1 = y;
y2 = y + 18;
icon = ico;
color = 0xffffff;
this.textSide = textSide;
}
public MenuButton(final String name, /*final ButtonAction action,*/ final double x, final double y,
final int col, final EnumFacing textSide) {
this.name = name;
//this.action = action;
x1 = x;
x2 = x + 18;
y1 = y;
y2 = y + 18;
color = col;
this.textSide = textSide;
}
}
static class MenuRegion {
public final BuildModeEnum mode;
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public MenuRegion(final BuildModeEnum mode) {
this.mode = mode;
}
}
@Override
public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) {
//TODO chisels compat
// final ChiselToolType tool = ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND );
//
// if ( tool != null )
// {
// return;
// }
GlStateManager.pushMatrix();
GlStateManager.translate( 0.0F, 0.0F, 200.0F );
final int startColor = (int) ( visibility * 98 ) << 24;
final int endColor = (int) ( visibility * 128 ) << 24;
drawGradientRect(0, 0, width, height, startColor, endColor);
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
GlStateManager.disableAlpha();
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.shadeModel(GL11.GL_SMOOTH);
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder buffer = tessellator.getBuffer();
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
final double middleX = width / 2.0;
final double middleY = height / 2.0;
final double mouseXCenter = mouseX - middleX;
final double mouseYCenter = mouseY - middleY;
double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter);
final double ringInnerEdge = 20;
final double ringOuterEdge = 50;
final double textDistance = 65;
final double quarterCircle = Math.PI / 2.0;
if ( mouseRadians < -quarterCircle ) {
mouseRadians = mouseRadians + Math.PI * 2;
}
final ArrayList<MenuRegion> modes = new ArrayList<MenuRegion>();
final ArrayList<MenuButton> buttons = new ArrayList<MenuButton>();
// buttons.add( new MenuButton( "mod.chiselsandbits.other.undo", ButtonAction.UNDO, textDistance, -20, ClientSide.undoIcon, EnumFacing.EAST ) );
// buttons.add( new MenuButton( "mod.chiselsandbits.other.redo", ButtonAction.REDO, textDistance, 4, ClientSide.redoIcon, EnumFacing.EAST ) );
for (final BuildModeEnum mode : BuildModeEnum.values()) {
modes.add(new MenuRegion(mode));
}
switchTo = null;
//doAction = null;
if (!modes.isEmpty()) {
final int totalModes = Math.max( 3, modes.size() );
int currentMode = 0;
final double fragment = Math.PI * 0.005;
final double fragment2 = Math.PI * 0.0025;
final double perObject = 2.0 * Math.PI / totalModes;
for (int i = 0; i < modes.size(); i++) {
MenuRegion menuRegion = modes.get(i);
final double beginRadians = currentMode * perObject - quarterCircle;
final double endRadians = (currentMode + 1) * perObject - quarterCircle;
menuRegion.x1 = Math.cos(beginRadians);
menuRegion.x2 = Math.cos(endRadians);
menuRegion.y1 = Math.sin(beginRadians);
menuRegion.y2 = Math.sin(endRadians);
final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge;
final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge;
final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge;
final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge;
final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge;
final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge;
final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge;
final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge;
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 0.5f;
//check if current mode
int buildMode = ModeSettingsManager.getModeSettings(Minecraft.getMinecraft().player).getBuildMode().ordinal();
if (buildMode == i) {
r = 0f;
g = 0.5f;
b = 1f;
a = 0.5f;
//menuRegion.highlighted = true; //draw text
}
//check if mouse is over this region
final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter)
|| inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter);
if (beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad) {
r = 0.6f;//0.6f;
g = 0.8f;//0.3f;
b = 1f;//0.0f;
a = 0.6f;
menuRegion.highlighted = true;
switchTo = menuRegion.mode;
}
buffer.pos(middleX + x1m1, middleY + y1m1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x2m1, middleY + y2m1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x2m2, middleY + y2m2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x1m2, middleY + y1m2, zLevel).color(r, g, b, a).endVertex();
currentMode++;
}
}
for (final MenuButton btn : buttons) {
final float a = 0.5f;
float f = 0f;
if (btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter) {
f = 1;
btn.highlighted = true;
//doAction = btn.action;
}
buffer.pos(middleX + btn.x1, middleY + btn.y1, zLevel).color(f, f, f, a).endVertex();
buffer.pos(middleX + btn.x1, middleY + btn.y2, zLevel).color(f, f, f, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y2, zLevel).color(f, f, f, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y1, zLevel).color(f, f, f, a).endVertex();
}
tessellator.draw();
GlStateManager.shadeModel(GL11.GL_FLAT);
GlStateManager.translate(0f, 0f, 5f);
GlStateManager.enableTexture2D();
GlStateManager.color(1f, 1f, 1f, 1f);
GlStateManager.disableBlend();
GlStateManager.enableAlpha();
GlStateManager.bindTexture(Minecraft.getMinecraft().getTextureMapBlocks().getGlTextureId());
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
for (final MenuRegion mnuRgn : modes) {
final double x = (mnuRgn.x1 + mnuRgn.x2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final double y = (mnuRgn.y1 + mnuRgn.y2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final TextureAtlasSprite sprite = ClientProxy.getBuildModeIcon(mnuRgn.mode);
final double scalex = 16 * 0.5;
final double scaley = 16 * 0.5;
final double x1 = x - scalex;
final double x2 = x + scalex;
final double y1 = y - scaley;
final double y2 = y + scaley;
final float f = 1f;
final float a = 1f;
final double u1 = 0f;
final double u2 = 16f;
final double v1 = 0f;
final double v2 = 16f;
buffer.pos(middleX + x1, middleY + y1, zLevel).tex( sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x1, middleY + y2, zLevel).tex( sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x2, middleY + y2, zLevel).tex( sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x2, middleY + y1, zLevel).tex( sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
}
for (final MenuButton btn : buttons) {
final float f = switchTo == null ? 1.0f : 0.5f;
final float a = 1.0f;
final double u1 = 0;
final double u2 = 16;
final double v1 = 0;
final double v2 = 16;
final TextureAtlasSprite sprite = btn.icon == null ? Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(ModelLoader.White.LOCATION.toString()) : btn.icon;
final double btnx1 = btn.x1 + 1;
final double btnx2 = btn.x2 - 1;
final double btny1 = btn.y1 + 1;
final double btny2 = btn.y2 - 1;
final float red = f * ((btn.color >> 16 & 0xff) / 255.0f);
final float green = f * ((btn.color >> 8 & 0xff) / 255.0f);
final float blue = f * ((btn.color & 0xff) / 255.0f);
buffer.pos(middleX + btnx1, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(red, green, blue, a).endVertex();
buffer.pos(middleX + btnx1, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(red, green, blue, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(red, green, blue, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(red, green, blue, a).endVertex();
}
tessellator.draw();
for (final MenuRegion mnuRgn : modes) {
if (mnuRgn.highlighted) {
final double x = (mnuRgn.x1 + mnuRgn.x2) * 0.5;
final double y = (mnuRgn.y1 + mnuRgn.y2) * 0.5;
int fixed_x = (int) (x * textDistance);
final int fixed_y = (int) (y * textDistance);
final String text = mnuRgn.mode.name;
if ( x <= -0.2 ) {
fixed_x -= fontRenderer.getStringWidth(text);
} else if ( -0.2 <= x && x <= 0.2 ) {
fixed_x -= fontRenderer.getStringWidth(text) / 2;
}
fontRenderer.drawStringWithShadow(text, (int) middleX + fixed_x, (int) middleY + fixed_y, 0xffffffff);
}
}
for (final MenuButton btn : buttons) {
if (btn.highlighted) {
final String text = btn.name;
if (btn.textSide == EnumFacing.WEST) {
fontRenderer.drawStringWithShadow( text, (int) ( middleX + btn.x1 - 8 ) - fontRenderer.getStringWidth( text ),
(int) ( middleY + btn.y1 + 6 ), 0xffffffff );
} else if (btn.textSide == EnumFacing.EAST) {
fontRenderer.drawStringWithShadow( text, (int) ( middleX + btn.x2 + 8 ),
(int) ( middleY + btn.y1 + 6 ), 0xffffffff );
} else if (btn.textSide == EnumFacing.UP) {
fontRenderer.drawStringWithShadow( text, (int) ( middleX + ( btn.x1 + btn.x2 ) * 0.5 - fontRenderer.getStringWidth( text ) * 0.5 ),
(int) ( middleY + btn.y1 - 14 ), 0xffffffff );
} else if (btn.textSide == EnumFacing.DOWN) {
fontRenderer.drawStringWithShadow( text, (int) ( middleX + ( btn.x1 + btn.x2 ) * 0.5 - fontRenderer.getStringWidth( text ) * 0.5 ),
(int) ( middleY + btn.y1 + 24 ), 0xffffffff );
}
}
}
GlStateManager.popMatrix();
}
private boolean inTriangle(final double x1, final double y1, final double x2, final double y2,
final double x3, final double y3, final double x, final double y ) {
final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y);
final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y);
final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y);
return sign(ab) == sign(bc) && sign(bc) == sign(ca);
}
private int sign(final double n) {
return n > 0 ? 1 : -1;
}
/**
* Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton
*/
protected void mouseClicked(int mouseX, int mouseY, int mouseButton ) {
if (mouseButton == 0) {
this.mc.displayGuiScreen(null);
if (this.mc.currentScreen == null) {
this.mc.setIngameFocus();
}
}
}
}

View File

@@ -1,13 +1,16 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.config.GuiCheckBox; 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.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException; import java.io.IOException;
@@ -55,9 +58,9 @@ public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
textArrayCount.setTooltip("How many copies should be made."); textArrayCount.setTooltip("How many copies should be made.");
arrayNumberFieldList.add(textArrayCount); arrayNumberFieldList.add(textArrayCount);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (buildSettings != null) { if (modifierSettings != null) {
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = modifierSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled); buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX()); textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY()); textArrayOffsetY.setNumber(a.offset.getY());

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
@@ -6,9 +6,13 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.config.GuiCheckBox; import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiIconButton;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException; import java.io.IOException;
@@ -94,9 +98,9 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
buttonDrawPlanes.setTooltip("Show area"); buttonDrawPlanes.setTooltip("Show area");
mirrorIconButtonList.add(buttonDrawPlanes); mirrorIconButtonList.add(buttonDrawPlanes);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (buildSettings != null) { if (modifierSettings != null) {
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled); buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x); textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y); textMirrorPosY.setNumber(m.position.y);

View File

@@ -1,14 +1,19 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.buildmodifier;
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 nl.requios.effortlessbuilding.*; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.io.IOException; import java.io.IOException;
public class SettingsGui extends GuiScreen { public class ModifierSettingsGui extends GuiScreen {
private GuiScrollPane scrollPane; private GuiScrollPane scrollPane;
private GuiButton buttonClose; private GuiButton buttonClose;
@@ -113,20 +118,20 @@ public class SettingsGui extends GuiScreen {
Array.ArraySettings a = arraySettingsGui.getArraySettings(); Array.ArraySettings a = arraySettingsGui.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (buildSettings == null) buildSettings = new BuildSettingsManager.BuildSettings(); if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings();
buildSettings.setMirrorSettings(m); modifierSettings.setMirrorSettings(m);
buildSettings.setArraySettings(a); modifierSettings.setArraySettings(a);
buildSettings.setRadialMirrorSettings(r); modifierSettings.setRadialMirrorSettings(r);
//Sanitize //Sanitize
String error = BuildSettingsManager.sanitize(buildSettings, mc.player); String error = ModifierSettingsManager.sanitize(modifierSettings, mc.player);
if (!error.isEmpty()) EffortlessBuilding.log(mc.player, error); if (!error.isEmpty()) EffortlessBuilding.log(mc.player, error);
BuildSettingsManager.setBuildSettings(mc.player, buildSettings); ModifierSettingsManager.setModifierSettings(mc.player, modifierSettings);
//Send to server //Send to server
EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); EffortlessBuilding.packetHandler.sendToServer(new ModifierSettingsMessage(modifierSettings));
} }
} }

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
@@ -6,9 +6,13 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.config.GuiCheckBox; import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.RadialMirror; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiIconButton;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException; import java.io.IOException;
@@ -94,9 +98,9 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
buttonRadialMirrorAlternate = new GuiCheckBox(id++, left + 140, y, " Alternate", false); buttonRadialMirrorAlternate = new GuiCheckBox(id++, left + 140, y, " Alternate", false);
radialMirrorButtonList.add(buttonRadialMirrorAlternate); radialMirrorButtonList.add(buttonRadialMirrorAlternate);
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (buildSettings != null) { if (modifierSettings != null) {
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
buttonRadialMirrorEnabled.setIsChecked(r.enabled); buttonRadialMirrorEnabled.setIsChecked(r.enabled);
textRadialMirrorPosX.setNumber(r.position.x); textRadialMirrorPosX.setNumber(r.position.x);
textRadialMirrorPosY.setNumber(r.position.y); textRadialMirrorPosY.setNumber(r.position.y);

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*; import net.minecraft.client.gui.*;
@@ -12,8 +12,8 @@ import java.util.List;
public class GuiNumberField extends Gui { public class GuiNumberField extends Gui {
int x, y, width, height; public int x, y, width, height;
int buttonWidth = 10; public int buttonWidth = 10;
protected GuiTextField textField; protected GuiTextField textField;
protected GuiButton minusButton, plusButton; protected GuiButton minusButton, plusButton;
@@ -106,7 +106,7 @@ public class GuiNumberField extends Gui {
} }
protected void actionPerformed(GuiButton button) { public void actionPerformed(GuiButton button) {
float valueChanged = 1f; float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f; if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f; if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
@@ -123,7 +123,7 @@ public class GuiNumberField extends Gui {
textField.updateCursorCounter(); textField.updateCursorCounter();
} }
protected void keyTyped(char typedChar, int keyCode) throws IOException { public void keyTyped(char typedChar, int keyCode) throws IOException {
if (!textField.isFocused()) return; if (!textField.isFocused()) return;
// if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK // 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_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;

View File

@@ -1,8 +1,9 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.MathHelper;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
public class ReachHelper { public class ReachHelper {
public static int getMaxReach(EntityPlayer player) { public static int getMaxReach(EntityPlayer player) {
@@ -11,7 +12,7 @@ public class ReachHelper {
if (!BuildConfig.reach.enableReachUpgrades) return BuildConfig.reach.maxReachLevel3; if (!BuildConfig.reach.enableReachUpgrades) return BuildConfig.reach.maxReachLevel3;
//Check buildsettings for reachUpgrade //Check buildsettings for reachUpgrade
int reachUpgrade = BuildSettingsManager.getBuildSettings(player).getReachUpgrade(); int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
switch (reachUpgrade) { switch (reachUpgrade) {
case 0: return BuildConfig.reach.maxReachLevel0; case 0: return BuildConfig.reach.maxReachLevel0;
case 1: return BuildConfig.reach.maxReachLevel1; case 1: return BuildConfig.reach.maxReachLevel1;
@@ -21,6 +22,20 @@ public class ReachHelper {
return BuildConfig.reach.maxReachLevel0; return BuildConfig.reach.maxReachLevel0;
} }
public static int getPlacementReach(EntityPlayer player) {
return getMaxReach(player) / 4;
}
public static int getMaxBlocksPlacedAtOnce(EntityPlayer player) {
if (player.isCreative()) return 1000000;
return getMaxReach(player) * 5;
}
public static int getMaxBlocksPerAxis(EntityPlayer player) {
if (player.isCreative()) return 2000;
return MathHelper.ceil(MathHelper.sqrt(getMaxReach(player)));
}
public static boolean canBreakFar(EntityPlayer player) { public static boolean canBreakFar(EntityPlayer player) {
return player.isCreative() || BuildConfig.survivalBalancers.breakFar; return player.isCreative() || BuildConfig.survivalBalancers.breakFar;
} }

View File

@@ -1,435 +0,0 @@
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, true, 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

@@ -13,20 +13,22 @@ import net.minecraft.init.Enchantments;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess; import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class SurvivalHelper { public class SurvivalHelper {
@@ -34,53 +36,36 @@ public class SurvivalHelper {
//Used for all placing of blocks in this mod. //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. //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 //Based on ItemBlock#onItemUse
public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState, ItemStack itemstack, EnumFacing facing, boolean skipCollisionCheck, boolean playSound) { public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState,
ItemStack origstack, EnumFacing facing, Vec3d hitVec, boolean skipCollisionCheck, boolean playSound) {
if (!world.isBlockLoaded(pos, true)) return false; if (!world.isBlockLoaded(pos, true)) return false;
ItemStack itemstack = origstack;
//Randomizer bag synergy //Randomizer bag, other proxy item synergy
//Find itemstack that belongs to the blockstate //Preliminary compatibility code for other items that hold blocks
if (itemstack.getItem() == EffortlessBuilding.ITEM_RANDOMIZER_BAG) { if(CompatHelper.isItemBlockProxy(itemstack))
IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(itemstack); itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
itemstack = ItemRandomizerBag.findStack(bagInventory, Item.getItemFromBlock(blockState.getBlock()));
}
//Check if itemstack is correct if(!(itemstack.getItem() instanceof ItemBlock))
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; return false;
}
Block block = ((ItemBlock) itemstack.getItem()).getBlock(); Block block = ((ItemBlock) itemstack.getItem()).getBlock();
if (!itemstack.isEmpty() && canPlayerEdit(player, world, pos, itemstack) && if (canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) {
mayPlace(world, block, blockState, pos, skipCollisionCheck, facing.getOpposite(), player) &&
canReplace(world, player, pos))
{
//Drop existing block //Drop existing block
//TODO check if can replace
dropBlock(world, player, pos); dropBlock(world, player, pos);
//From ItemBlock#placeBlockAt boolean placed = ((ItemBlock) itemstack.getItem()).placeBlockAt(itemstack, player, world, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, blockState);
if (!world.setBlockState(pos, blockState, 11)) return false; if (!placed) return false;
IBlockState state = world.getBlockState(pos); IBlockState afterState = 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) { if (playSound) {
SoundType soundtype = state.getBlock().getSoundType(state, world, pos, player); SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player);
world.playSound(null, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); 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) { if (!player.isCreative() && Block.getBlockFromItem(itemstack.getItem()) == block) {
itemstack.shrink(1); CompatHelper.shrinkStack(origstack, itemstack);
} }
return true; return true;
@@ -96,6 +81,9 @@ public class SurvivalHelper {
//Check if can break //Check if can break
if (canBreak(world, player, pos)) if (canBreak(world, player, pos))
{ {
// player.addStat(StatList.getBlockStats(world.getBlockState(pos).getBlock()));
// player.addExhaustion(0.005F);
//Drop existing block //Drop existing block
dropBlock(world, player, pos); dropBlock(world, player, pos);
@@ -108,6 +96,133 @@ public class SurvivalHelper {
return false; 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());
//TODO drop items in inventory instead of world
// List<ItemStack> drops = new ArrayList<>();
//
// //From Block#harvestBlock
// int silktouch = EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, player.getHeldItemMainhand());
// if (block.canSilkHarvest(world, pos, blockState, player) && silktouch > 0) {
//
// //From Block#getSilkTouchDrop (protected)
// Item item = Item.getItemFromBlock(block);
// int i = 0;
//
// if (item.getHasSubtypes())
// {
// i = block.getMetaFromState(blockState);
// }
//
// drops.add(new ItemStack(item, 1, i));
//
// net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(drops, world, pos, blockState, 0, 1.0f, true, player);
// }
//
// int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand());
// drops.addAll(block.getDrops(world, pos, blockState, fortune));
// for (ItemStack drop : drops)
// {
// ItemHandlerHelper.giveItemToPlayer(player, drop);
// }
}
/**
* Check if player can place a block.
* Turn randomizer bag into itemstack inside before.
* @param world
* @param player
* @param pos
* @param newBlockState the blockstate that is going to be placed
* @param itemStack the itemstack used for placing
* @param skipCollisionCheck skips collision check with entities
* @param sidePlacedOn
* @return Whether the player may place the block at pos with itemstack
*/
public static boolean canPlace(World world, EntityPlayer player, BlockPos pos, IBlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, EnumFacing sidePlacedOn) {
//Check if itemstack is correct
if (!(itemStack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) {
// EffortlessBuilding.log(player, "Cannot (re)place block", true);
// EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString());
//Happens when breaking blocks, no need to notify in that case
return false;
}
Block block = ((ItemBlock) itemStack.getItem()).getBlock();
return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) &&
mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) &&
canReplace(world, player, pos);
}
//Can be harvested with hand? (or in creative)
private 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;
}
//From EntityPlayer#canPlayerEdit
private 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
private 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 && ModifierSettingsManager.getModifierSettings(((EntityPlayer) placer)).doQuickReplace()) {
return true;
}
return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
}
//Can break using held tool? (or in creative) //Can break using held tool? (or in creative)
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) { public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
IBlockState blockState = world.getBlockState(pos); IBlockState blockState = world.getBlockState(pos);
@@ -123,6 +238,12 @@ public class SurvivalHelper {
{ {
IBlockState state = world.getBlockState(pos); IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos); state = state.getBlock().getActualState(state, world, pos);
//Dont break bedrock
if (state.getBlockHardness((World) world, pos) < 0) {
return false;
}
if (state.getMaterial().isToolNotRequired()) if (state.getMaterial().isToolNotRequired())
{ {
return true; return true;
@@ -145,75 +266,4 @@ public class SurvivalHelper {
return toolLevel >= block.getHarvestLevel(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);
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 ? null : blockIn.getDefaultState().getCollisionBoundingBox(world, pos);
if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos), placer))
{
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,6 +13,7 @@ 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;
@@ -36,7 +37,7 @@ public class ItemRandomizerBag extends Item {
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.TOOLS); this.setCreativeTab(CreativeTabs.TOOLS);
@@ -72,7 +73,7 @@ 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);
SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, false, true); SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(hitX, hitY, hitZ), false, true);
//Synergy //Synergy
//Works without calling //Works without calling
@@ -181,8 +182,8 @@ public class ItemRandomizerBag extends Item {
} }
@Override @Override
public String getUnlocalizedName() { public String getTranslationKey() {
return super.getUnlocalizedName(); return super.getTranslationKey();
} }
public static void resetRandomness() { public static void resetRandomness() {

View File

@@ -10,8 +10,8 @@ import net.minecraft.util.*;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -21,7 +21,7 @@ public class ItemReachUpgrade1 extends Item {
public ItemReachUpgrade1() { public ItemReachUpgrade1() {
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1"); this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1");
this.setUnlocalizedName(this.getRegistryName().toString()); this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1; this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS); this.setCreativeTab(CreativeTabs.TOOLS);
@@ -35,12 +35,12 @@ public class ItemReachUpgrade1 extends Item {
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
} }
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = buildSettings.getReachUpgrade(); int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 0) { if (currentLevel == 0) {
buildSettings.setReachUpgrade(1); modifierSettings.setReachUpgrade(1);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player)); if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY); player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup")); SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
@@ -67,7 +67,7 @@ public class ItemReachUpgrade1 extends Item {
} }
@Override @Override
public String getUnlocalizedName() { public String getTranslationKey() {
return super.getUnlocalizedName(); return super.getTranslationKey();
} }
} }

View File

@@ -9,8 +9,8 @@ import net.minecraft.util.*;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -20,7 +20,7 @@ public class ItemReachUpgrade2 extends Item {
public ItemReachUpgrade2() { public ItemReachUpgrade2() {
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2"); this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2");
this.setUnlocalizedName(this.getRegistryName().toString()); this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1; this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS); this.setCreativeTab(CreativeTabs.TOOLS);
@@ -34,11 +34,11 @@ public class ItemReachUpgrade2 extends Item {
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
} }
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = buildSettings.getReachUpgrade(); int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 1) { if (currentLevel == 1) {
buildSettings.setReachUpgrade(2); modifierSettings.setReachUpgrade(2);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player)); if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY); player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup")); SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
@@ -65,7 +65,7 @@ public class ItemReachUpgrade2 extends Item {
} }
@Override @Override
public String getUnlocalizedName() { public String getTranslationKey() {
return super.getUnlocalizedName(); return super.getTranslationKey();
} }
} }

View File

@@ -9,8 +9,8 @@ import net.minecraft.util.*;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -20,7 +20,7 @@ public class ItemReachUpgrade3 extends Item {
public ItemReachUpgrade3() { public ItemReachUpgrade3() {
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3"); this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3");
this.setUnlocalizedName(this.getRegistryName().toString()); this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1; this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS); this.setCreativeTab(CreativeTabs.TOOLS);
@@ -34,11 +34,11 @@ public class ItemReachUpgrade3 extends Item {
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
} }
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = buildSettings.getReachUpgrade(); int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 2) { if (currentLevel == 2) {
buildSettings.setReachUpgrade(3); modifierSettings.setReachUpgrade(3);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player)); if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY); player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup")); SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
@@ -68,7 +68,7 @@ public class ItemReachUpgrade3 extends Item {
} }
@Override @Override
public String getUnlocalizedName() { public String getTranslationKey() {
return super.getUnlocalizedName(); return super.getTranslationKey();
} }
} }

View File

@@ -9,9 +9,13 @@ 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.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
/***
* Sends a message to the server indicating that a player wants to break a block
*/
public class BlockBrokenMessage implements IMessage { public class BlockBrokenMessage implements IMessage {
private boolean blockHit; private boolean blockHit;
@@ -65,7 +69,7 @@ public class BlockBrokenMessage implements IMessage {
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()); hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
} }
@@ -80,7 +84,7 @@ public class BlockBrokenMessage implements IMessage {
if (ctx.side == Side.SERVER) { if (ctx.side == Side.SERVER) {
//Received serverside //Received serverside
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> { EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
BuildModifiers.onBlockBrokenMessage(ctx.getServerHandler().player, message); BuildModes.onBlockBrokenMessage(ctx.getServerHandler().player, message);
}); });
} }
// No response packet // No response packet

View File

@@ -9,10 +9,16 @@ 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.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
/***
* Sends a message to the server indicating that a player wants to place a block.
* Received clientside: server has placed blocks and its letting the client know.
*/
public class BlockPlacedMessage implements IMessage { public class BlockPlacedMessage implements IMessage {
private boolean blockHit; private boolean blockHit;
@@ -66,7 +72,7 @@ public class BlockPlacedMessage implements IMessage {
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()); hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
} }
@@ -80,12 +86,15 @@ public class BlockPlacedMessage implements IMessage {
if (ctx.side == Side.CLIENT){ if (ctx.side == Side.CLIENT){
//Received clientside //Received clientside
//Send back your info EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
return new BlockPlacedMessage(ClientProxy.previousLookAt); //Nod RenderHandler to do the dissolve shader effect
BlockPreviewRenderer.onBlocksPlaced();
});
return null;
} else { } else {
//Received serverside //Received serverside
EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> { EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
BuildModifiers.onBlockPlacedMessage(ctx.getServerHandler().player, message); BuildModes.onBlockPlacedMessage(ctx.getServerHandler().player, message);
}); });
// No response packet // No response packet
return null; return null;

View File

@@ -0,0 +1,45 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.IThreadListener;
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 nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
/**
* Sends a message to the server indicating that a buildmode needs to be canceled for a player
*/
public class CancelModeMessage implements IMessage {
@Override
public void toBytes(ByteBuf buf) {
}
@Override
public void fromBytes(ByteBuf buf) {
}
// The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<CancelModeMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(CancelModeMessage message, MessageContext ctx) {
// Execute the action on the main server thread by adding it as a scheduled task
IThreadListener threadListener = EffortlessBuilding.proxy.getThreadListenerFromContext(ctx);
threadListener.addScheduledTask(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
BuildModes.initializeMode(player);
});
// No response packet
return null;
}
}
}

View File

@@ -0,0 +1,70 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.IThreadListener;
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 nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.*;
/**
* Shares mode settings (see ModeSettingsManager) between server and client
*/
public class ModeSettingsMessage implements IMessage {
private ModeSettings modeSettings;
public ModeSettingsMessage() {
}
public ModeSettingsMessage(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeInt(modeSettings.getBuildMode().ordinal());
//TODO add mode settings
}
@Override
public void fromBytes(ByteBuf buf) {
BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()];
//TODO add mode settings
modeSettings = new ModeSettings(buildMode);
}
// The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<ModeSettingsMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(ModeSettingsMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side");
// The value that was sent
ModeSettings modeSettings = message.modeSettings;
// Execute the action on the main server thread by adding it as a scheduled task
IThreadListener threadListener = EffortlessBuilding.proxy.getThreadListenerFromContext(ctx);
threadListener.addScheduledTask(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize
ModeSettingsManager.sanitize(modeSettings, player);
ModeSettingsManager.setModeSettings(player, modeSettings);
});
// No response packet
return null;
}
}
}

View File

@@ -8,24 +8,32 @@ 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.*; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
public class BuildSettingsMessage implements IMessage { import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.*;
private BuildSettings buildSettings; /**
* Shares modifier settings (see ModifierSettingsManager) between server and client
*/
public class ModifierSettingsMessage implements IMessage {
public BuildSettingsMessage() { private ModifierSettings modifierSettings;
public ModifierSettingsMessage() {
} }
public BuildSettingsMessage(BuildSettings buildSettings) { public ModifierSettingsMessage(ModifierSettings modifierSettings) {
this.buildSettings = buildSettings; this.modifierSettings = modifierSettings;
} }
@Override @Override
public void toBytes(ByteBuf buf) { public void toBytes(ByteBuf buf) {
//MIRROR //MIRROR
Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
buf.writeBoolean(m != null); buf.writeBoolean(m != null);
if (m != null) { if (m != null) {
buf.writeBoolean(m.enabled); buf.writeBoolean(m.enabled);
@@ -41,7 +49,7 @@ public class BuildSettingsMessage implements IMessage {
} }
//ARRAY //ARRAY
Array.ArraySettings a = buildSettings.getArraySettings(); Array.ArraySettings a = modifierSettings.getArraySettings();
buf.writeBoolean(a != null); buf.writeBoolean(a != null);
if (a != null) { if (a != null) {
buf.writeBoolean(a.enabled); buf.writeBoolean(a.enabled);
@@ -51,12 +59,12 @@ public class BuildSettingsMessage implements IMessage {
buf.writeInt(a.count); buf.writeInt(a.count);
} }
buf.writeBoolean(buildSettings.doQuickReplace()); buf.writeBoolean(modifierSettings.doQuickReplace());
buf.writeInt(buildSettings.getReachUpgrade()); buf.writeInt(modifierSettings.getReachUpgrade());
//RADIAL MIRROR //RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null); buf.writeBoolean(r != null);
if (r != null) { if (r != null) {
buf.writeBoolean(r.enabled); buf.writeBoolean(r.enabled);
@@ -115,19 +123,19 @@ public class BuildSettingsMessage implements IMessage {
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes); radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
} }
buildSettings = new BuildSettings(m, a, r, quickReplace, reachUpgrade); modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade);
} }
// The params of the IMessageHandler are <REQ, REPLY> // The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<BuildSettingsMessage, IMessage> { public static class MessageHandler implements IMessageHandler<ModifierSettingsMessage, 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(BuildSettingsMessage message, MessageContext ctx) { public IMessage onMessage(ModifierSettingsMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side"); //EffortlessBuilding.log("message received on " + ctx.side + " side");
// The value that was sent // The value that was sent
BuildSettings buildSettings = message.buildSettings; ModifierSettings modifierSettings = message.modifierSettings;
// 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);
@@ -135,9 +143,9 @@ public class BuildSettingsMessage implements IMessage {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize // Sanitize
BuildSettingsManager.sanitize(buildSettings, player); ModifierSettingsManager.sanitize(modifierSettings, player);
BuildSettingsManager.setBuildSettings(player, buildSettings); ModifierSettingsManager.setModifierSettings(player, modifierSettings);
}); });
// No response packet // No response packet
return null; return null;

View File

@@ -0,0 +1,50 @@
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.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
/***
* Sends a message to the client asking for its lookat (objectmouseover) data.
* This is then sent back with a BlockPlacedMessage.
*/
public class RequestLookAtMessage implements IMessage {
public RequestLookAtMessage() {
}
@Override
public void toBytes(ByteBuf buf) {
}
@Override
public void fromBytes(ByteBuf buf) {
}
// The params of the IMessageHandler are <REQ, REPLY>
public static class MessageHandler implements IMessageHandler<RequestLookAtMessage, IMessage> {
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(RequestLookAtMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side");
if (ctx.side == Side.CLIENT){
//Received clientside
//Send back your info
return new BlockPlacedMessage(ClientProxy.previousLookAt);
}
return null;
}
}
}

View File

@@ -5,20 +5,25 @@ import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState; 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.gui.GuiScreen;
import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.settings.KeyBinding; 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.item.ItemStack;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.IThreadListener; import net.minecraft.util.IThreadListener;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
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.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.client.registry.ClientRegistry;
@@ -34,18 +39,21 @@ 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.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.gui.SettingsGui; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.RenderHelper; import nl.requios.effortlessbuilding.render.RenderHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.render.ShaderHandler;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage; import nl.requios.effortlessbuilding.network.*;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.util.HashMap;
@Mod.EventBusSubscriber(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT)
public class ClientProxy implements IProxy { public class ClientProxy implements IProxy {
public static KeyBinding[] keyBindings; public static KeyBinding[] keyBindings;
@@ -53,19 +61,26 @@ public class ClientProxy implements IProxy {
public static RayTraceResult currentLookAt; public static RayTraceResult currentLookAt;
private static int breakCooldown = 0; private static int breakCooldown = 0;
public static int ticksInGame = 0;
private static final HashMap<BuildModes.BuildModeEnum, TextureAtlasSprite> buildModeIcons = new HashMap<>();
@Override @Override
public void preInit(FMLPreInitializationEvent event) { public void preInit(FMLPreInitializationEvent event) {
ShaderHandler.init();
} }
@Override @Override
public void init(FMLInitializationEvent event) { public void init(FMLInitializationEvent event) {
// register key bindings // register key bindings
keyBindings = new KeyBinding[3]; keyBindings = new KeyBinding[4];
// instantiate the key bindings // instantiate the key bindings
keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category"); keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category"); keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_F4, "key.effortlessbuilding.category"); keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_NONE, "key.effortlessbuilding.category");
keyBindings[3] = new KeyBinding("key.effortlessbuilding.mode.desc", Keyboard.KEY_LMENU, "key.effortlessbuilding.category");
// keyBindings[4] = new KeyBinding("Reload shaders", Keyboard.KEY_TAB, "key.effortlessbuilding.category");
// register all the key bindings // register all the key bindings
for (int i = 0; i < keyBindings.length; ++i) { for (int i = 0; i < keyBindings.length; ++i) {
@@ -107,37 +122,58 @@ public class ClientProxy implements IProxy {
@SubscribeEvent @SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event) { public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getEntity() == Minecraft.getMinecraft().player) { if (event.getEntity() == Minecraft.getMinecraft().player) {
event.getWorld().addEventListener(new RenderHelper()); event.getWorld().addEventListener(new RenderHandler());
} }
} }
@SubscribeEvent
public static void onTextureStitch(final TextureStitchEvent.Pre event) {
//register icon textures
final TextureMap map = event.getMap();
for ( final BuildModes.BuildModeEnum mode : BuildModes.BuildModeEnum.values() )
{
final ResourceLocation sprite = new ResourceLocation("effortlessbuilding", "icons/" + mode.name().toLowerCase());
buildModeIcons.put( mode, map.registerSprite(sprite));
}
}
public static TextureAtlasSprite getBuildModeIcon(BuildModes.BuildModeEnum mode) {
return buildModeIcons.get(mode);
}
@SubscribeEvent @SubscribeEvent
public static void onMouseInput(InputEvent.MouseInputEvent event) { public static void onMouseInput(InputEvent.MouseInputEvent event) {
Minecraft mc = Minecraft.getMinecraft(); Minecraft mc = Minecraft.getMinecraft();
EntityPlayerSP player = mc.player; EntityPlayerSP player = mc.player;
if (!BuildModifiers.isEnabled(BuildSettingsManager.getBuildSettings(player), player.getPosition())) return; if (Minecraft.getMinecraft().currentScreen != null ||
ModeSettingsManager.getModeSettings(player).getBuildMode() == BuildModes.BuildModeEnum.Normal ||
RadialMenu.instance.isVisible()) {
return;
}
if (mc.gameSettings.keyBindUseItem.isPressed()) { if (mc.gameSettings.keyBindUseItem.isPressed()) {
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false); //KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND); ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (currentItemStack.getItem() instanceof ItemBlock || if (CompatHelper.isItemBlockProxy(currentItemStack) && !player.isSneaking()) {
(currentItemStack.getItem() instanceof ItemRandomizerBag && !player.isSneaking())) {
//find position in distance //find position in distance
RayTraceResult lookingAt = getLookingAt(player); RayTraceResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) { BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage(lookingAt));
EffortlessBuilding.packetHandler.sendToServer(new BlockPlacedMessage(lookingAt)); EffortlessBuilding.packetHandler.sendToServer(new BlockPlacedMessage(lookingAt));
//play sound if further than normal //play sound if further than normal
if ((lookingAt.hitVec.subtract(player.getPositionEyes(1f))).lengthSquared() > 25f) { if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK &&
BlockPos blockPos = lookingAt.getBlockPos(); (lookingAt.hitVec.subtract(player.getPositionEyes(1f))).lengthSquared() > 25f) {
IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player); BlockPos blockPos = lookingAt.getBlockPos();
player.world.playSound(player, blockPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, IBlockState state = player.world.getBlockState(blockPos);
(soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
player.swingArm(EnumHand.MAIN_HAND); player.world.playSound(player, blockPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS,
} (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
player.swingArm(EnumHand.MAIN_HAND);
} }
} }
} }
@@ -150,10 +186,12 @@ public class ClientProxy implements IProxy {
if (breakCooldown <= 0) { if (breakCooldown <= 0) {
breakCooldown = 6; breakCooldown = 6;
RayTraceResult lookingAt = getLookingAt(player); RayTraceResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
EffortlessBuilding.packetHandler.sendToServer(new BlockBrokenMessage(lookingAt));
//play sound BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage(lookingAt));
EffortlessBuilding.packetHandler.sendToServer(new BlockBrokenMessage(lookingAt));
//play sound
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
BlockPos blockPos = lookingAt.getBlockPos(); BlockPos blockPos = lookingAt.getBlockPos();
IBlockState state = player.world.getBlockState(blockPos); IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player); SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
@@ -165,6 +203,9 @@ public class ClientProxy implements IProxy {
breakCooldown--; breakCooldown--;
} }
} }
//EffortlessBuilding.packetHandler.sendToServer(new CancelModeMessage());
} else { } else {
breakCooldown = 0; breakCooldown = 0;
} }
@@ -180,10 +221,10 @@ public class ClientProxy implements IProxy {
if (keyBindings[0].isPressed()) { if (keyBindings[0].isPressed()) {
//Disabled if max reach is 0, might be set in the config that way. //Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.getMaxReach(player) == 0) { if (ReachHelper.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Effortless Building is disabled until your reach has increased. Increase your reach with craftable reach upgrades."); EffortlessBuilding.log(player, "Build modifiers are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else { } else {
if (Minecraft.getMinecraft().currentScreen == null) { if (Minecraft.getMinecraft().currentScreen == null) {
Minecraft.getMinecraft().displayGuiScreen(new SettingsGui()); Minecraft.getMinecraft().displayGuiScreen(new ModifierSettingsGui());
} else { } else {
player.closeScreen(); player.closeScreen();
} }
@@ -192,10 +233,11 @@ public class ClientProxy implements IProxy {
//QuickReplace toggle //QuickReplace toggle
if (keyBindings[1].isPressed()) { if (keyBindings[1].isPressed()) {
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
buildSettings.setQuickReplace(!buildSettings.doQuickReplace()); modifierSettings.setQuickReplace(!modifierSettings.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 + (
EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); modifierSettings.doQuickReplace() ? "on" : "off"));
EffortlessBuilding.packetHandler.sendToServer(new ModifierSettingsMessage(modifierSettings));
} }
//Creative/survival mode toggle //Creative/survival mode toggle
@@ -206,32 +248,53 @@ public class ClientProxy implements IProxy {
player.sendChatMessage("/gamemode 1"); player.sendChatMessage("/gamemode 1");
} }
} }
// if (keyBindings[4].isPressed()) {
// //TODO remove
// ShaderHandler.init();
// EffortlessBuilding.log(player, "Reloaded shaders");
// }
} }
@SubscribeEvent @SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) { public static void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; if (event.phase == TickEvent.Phase.START) {
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;
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; if (currentLookAt == null) {
//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 (currentLookAt == null) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
return;
}
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) {
if (currentLookAt.typeOfHit != RayTraceResult.Type.BLOCK) {
currentLookAt = objectMouseOver; currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver; previousLookAt = objectMouseOver;
} else { return;
if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()){ }
previousLookAt = currentLookAt;
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) {
if (currentLookAt.typeOfHit != RayTraceResult.Type.BLOCK) {
currentLookAt = objectMouseOver; currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()) {
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
} }
} }
} else if (event.phase == TickEvent.Phase.END){
GuiScreen gui = Minecraft.getMinecraft().currentScreen;
if(gui == null || !gui.doesGuiPauseGame()) {
ticksInGame++;
}
}
}
@SubscribeEvent
public static void onGuiOpen(GuiOpenEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
if (player != null) {
BuildModes.initializeMode(player);
} }
} }
@@ -239,7 +302,7 @@ public class ClientProxy implements IProxy {
// World world = player.world; // World world = player.world;
//base distance off of player ability (config) //base distance off of player ability (config)
float raytraceRange = ReachHelper.getMaxReach(player) / 4f; float raytraceRange = ReachHelper.getPlacementReach(player);
// Vec3d look = player.getLookVec(); // Vec3d look = player.getLookVec();
// Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); // Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);

View File

@@ -0,0 +1,372 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
@SideOnly(Side.CLIENT)
public class BlockPreviewRenderer {
private static List<BlockPos> previousCoordinates;
private static List<IBlockState> previousBlockStates;
private static List<ItemStack> previousItemStacks;
private static BlockPos previousFirstPos;
private static BlockPos previousSecondPos;
private static int soundTime = 0;
static class PlacedData {
float time;
List<BlockPos> coordinates;
List<IBlockState> blockStates;
List<ItemStack> itemStacks;
BlockPos firstPos;
BlockPos secondPos;
boolean breaking;
public PlacedData(float time, List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
this.time = time;
this.coordinates = coordinates;
this.blockStates = blockStates;
this.itemStacks = itemStacks;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.breaking = breaking;
}
}
private static List<PlacedData> placedDataList = new ArrayList<>();
private static final int secondaryTextureUnit = 7;
public static void render(EntityPlayer player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
//Render placed blocks with dissolve effect
//Use fancy shader if config allows, otherwise no dissolve
if (BuildConfig.visuals.useShaders) {
RenderHandler.beginBlockPreviews();
for (int i = 0; i < placedDataList.size(); i++) {
PlacedData placed = placedDataList.get(i);
if (placed.coordinates != null && !placed.coordinates.isEmpty()) {
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier;
float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) totalTime;
renderBlockPreviews(placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
}
}
RenderHandler.endBlockPreviews();
}
//Expire
placedDataList.removeIf(placed -> {
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier;
return placed.time + totalTime < ClientProxy.ticksInGame;
});
//Render block previews
RayTraceResult lookingAt = ClientProxy.getLookingAt(player);
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.Normal) lookingAt = Minecraft.getMinecraft().objectMouseOver;
ItemStack mainhand = player.getHeldItemMainhand();
boolean toolInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
BlockPos startPos = null;
EnumFacing sideHit = null;
Vec3d hitVec = null;
//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) {
startPos = lookingAt.getBlockPos();
//Check if tool (or none) in hand
boolean replaceable = player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable) {
startPos = startPos.offset(lookingAt.sideHit);
}
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down();
}
sideHit = lookingAt.sideHit;
hitVec = lookingAt.hitVec;
}
//Dont render if in normal mode and modifiers are disabled
//Unless alwaysShowBlockPreview is true in config
if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) {
IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
if (sideHit != null) {
//Should be red?
boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
//get coordinates
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN;
//Remember first and last pos for the shader
if (!startCoordinates.isEmpty()) {
firstPos = startCoordinates.get(0);
secondPos = startCoordinates.get(startCoordinates.size() - 1);
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (startCoordinates.size() > limit) {
startCoordinates = startCoordinates.subList(0, limit);
}
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
Collections.sort(newCoordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getPositionEyes(1f)).lengthSquared();
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getPositionEyes(1f)).lengthSquared();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z)));
//Get blockstates
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = new ArrayList<>();
if (breaking) {
//Find blockstate of world
for (BlockPos coordinate : newCoordinates) {
blockStates.add(player.world.getBlockState(coordinate));
}
} else {
blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
}
//Check if they are different from previous
//TODO fix triggering when moving player
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates;
//remember the rest for placed blocks
previousBlockStates = blockStates;
previousItemStacks = itemStacks;
previousFirstPos = firstPos;
previousSecondPos = secondPos;
//if so, renew randomness of randomizer bag
ItemRandomizerBag.renewRandomness();
//and play sound (max once every tick)
if (startCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) {
soundTime = ClientProxy.ticksInGame;
//player.playSound(EffortlessBuilding.SOUND_BUILD_CLICK, 0.2f, 1f);
player.playSound(blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world,
newCoordinates.get(0), player).getPlaceSound(), 0.3f, 1f);
}
}
//Render block previews
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
//Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders && newCoordinates.size() < BuildConfig.visuals.shaderTreshold) {
RenderHandler.beginBlockPreviews();
renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
RenderHandler.endBlockPreviews();
} else {
RenderHandler.beginLines();
Vec3d color = new Vec3d(1f, 1f, 1f);
if (breaking) color = new Vec3d(1f, 0f, 0f);
for (int i = newCoordinates.size() - 1; i >= 0; i--) {
RenderHandler.renderBlockOutline(newCoordinates.get(i), color);
}
RenderHandler.endLines();
}
}
}
RenderHandler.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) {
RenderHandler.renderBlockOutline(coordinate, new Vec3d(0f, 0f, 0f));
}
}
}
}
RenderHandler.endLines();
}
}
//Whether to draw any block previews or outlines
public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.Normal ||
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
BuildConfig.visuals.alwaysShowBlockPreview;
}
protected static void renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace, boolean red) {
EntityPlayer player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
if (coordinates.isEmpty()) return;
for (int i = coordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
//Check if can place
//If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getBlockState(blockPos) == blockState*/) ||
SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), EnumFacing.UP)) {
ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve,
new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos),
blockPos == secondPos, red));
RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState);
}
}
}
public static void onBlocksPlaced() {
EntityPlayerSP player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() &&
previousCoordinates.size() > 1 && previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates,
previousItemStacks, previousFirstPos, previousSecondPos, false));
}
}
}
public static void onBlocksBroken() {
EntityPlayerSP player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() &&
previousCoordinates.size() > 1 && previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates,
previousItemStacks, previousFirstPos, previousSecondPos, true));
}
}
}
private static Consumer<Integer> generateShaderCallback(final float dissolve, final Vec3d blockpos,
final Vec3d firstpos, final Vec3d secondpos,
final boolean highlight, final boolean red) {
Minecraft mc = Minecraft.getMinecraft();
return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve");
int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight");
int redUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "red");
int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos");
int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos");
int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos");
int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image");
int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask");
//image
OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).getGlTextureId());
ARBShaderObjects.glUniform1iARB(imageUniform, 0);
OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
GlStateManager.enableTexture2D();
GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
//mask
GL11.glBindTexture(GL11.GL_TEXTURE_2D,
mc.renderEngine.getTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png")).getGlTextureId());
ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit);
//blockpos
ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z);
ARBShaderObjects.glUniform3fARB(firstposUniform, (float) firstpos.x, (float) firstpos.y, (float) firstpos.z);
ARBShaderObjects.glUniform3fARB(secondposUniform, (float) secondpos.x, (float) secondpos.y, (float) secondpos.z);
//dissolve
ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve);
//highlight
ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0);
//red
ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0);
};
}
}

View File

@@ -0,0 +1,175 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.Color;
@SideOnly(Side.CLIENT)
public class ModifierRenderer {
protected static final Color colorX = new Color(255, 72, 52);
protected static final Color colorY = new Color(67, 204, 51);
protected static final Color colorZ = new Color(52, 247, 255);
protected static final Color colorRadial = new Color(52, 247, 255);
protected static final int lineAlpha = 200;
protected static final int planeAlpha = 75;
protected static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
public static void render(ModifierSettingsManager.ModifierSettings modifierSettings) {
RenderHandler.beginLines();
//Mirror lines and areas
Mirror.MirrorSettings m = modifierSettings.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 = modifierSettings.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);
}
}
RenderHandler.endLines();
}
//----Mirror----
protected 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();
}
}
protected 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();
}
}
protected 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();
}
}

View File

@@ -0,0 +1,302 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorldEventListener;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
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.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import javax.annotation.Nullable;
import java.util.List;
/***
* Main render class for Effortless Building
*/
@Mod.EventBusSubscriber(Side.CLIENT)
public class RenderHandler implements IWorldEventListener {
@SubscribeEvent
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
begin(event.getPartialTicks());
//Mirror and radial mirror lines and areas
ModifierRenderer.render(modifierSettings);
//Render block previews
BlockPreviewRenderer.render(player, modifierSettings, modeSettings);
end();
}
@SubscribeEvent
//Display Radial Menu
public static void onRenderGameOverlay(final RenderGameOverlayEvent.Post event ) {
Minecraft mc = Minecraft.getMinecraft();
EntityPlayerSP player = mc.player;
//check if chisel and bits tool in hand (and has menu)
final boolean hasChiselInHand = CompatHelper.chiselsAndBitsProxy.isHoldingChiselTool(EnumHand.MAIN_HAND);
final RenderGameOverlayEvent.ElementType type = event.getType();
if (type == RenderGameOverlayEvent.ElementType.ALL && !hasChiselInHand) {
final boolean wasVisible = RadialMenu.instance.isVisible();
if (ClientProxy.keyBindings[3].isKeyDown()) {
if (ReachHelper.getMaxReach(player) > 0) {
RadialMenu.instance.actionUsed = false;
RadialMenu.instance.raiseVisibility();
} else if (ClientProxy.keyBindings[3].isPressed()) {
EffortlessBuilding.log(player, "Build modes are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
}
} else {
if ( !RadialMenu.instance.actionUsed ) {
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
if ( RadialMenu.instance.switchTo != null ) {
playRadialMenuSound();
modeSettings.setBuildMode(RadialMenu.instance.switchTo);
ModeSettingsManager.setModeSettings(player, modeSettings);
EffortlessBuilding.packetHandler.sendToServer(new ModeSettingsMessage(modeSettings));
EffortlessBuilding.log(player, modeSettings.getBuildMode().name, true);
}
//TODO change buildmode settings
playRadialMenuSound();
}
RadialMenu.instance.actionUsed = true;
RadialMenu.instance.decreaseVisibility();
}
if (RadialMenu.instance.isVisible()) {
final ScaledResolution res = event.getResolution();
RadialMenu.instance.configure(res.getScaledWidth(), res.getScaledHeight());
if (!wasVisible) {
mc.inGameHasFocus = false;
mc.mouseHelper.ungrabMouseCursor();
}
if (mc.inGameHasFocus) {
KeyBinding.unPressAllKeys();
}
final int k1 = Mouse.getX() * res.getScaledWidth() / mc.displayWidth;
final int l1 = res.getScaledHeight() - Mouse.getY() * res.getScaledHeight() / mc.displayHeight - 1;
net.minecraftforge.client.ForgeHooksClient.drawScreen(RadialMenu.instance, k1, l1, event.getPartialTicks());
} else {
if (wasVisible) {
mc.setIngameFocus();
}
}
}
}
public static void playRadialMenuSound() {
final float volume = 0.1f;
if (volume >= 0.0001f) {
final PositionedSoundRecord psr = new PositionedSoundRecord(SoundEvents.UI_BUTTON_CLICK, SoundCategory.MASTER,
volume, 1.0f, Minecraft.getMinecraft().player.getPosition());
Minecraft.getMinecraft().getSoundHandler().playSound(psr);
}
}
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);
}
protected 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);
}
protected static void endLines() {
GL11.glPopAttrib();
}
protected 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);
Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png"));
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL14.glBlendColor(1F, 1F, 1F, 0.8f);
}
protected static void endBlockPreviews() {
ShaderHandler.releaseShader();
GlStateManager.disableBlend();
GL11.glPopAttrib();
}
private static void end() {
GL11.glDepthMask(true);
GL11.glPopMatrix();
}
protected 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.01f, -0.01f, 0.01f);
GlStateManager.scale(1.02f, 1.02f, 1.02f);
dispatcher.renderBlockBrightness(blockState, 0.85f);
GlStateManager.popMatrix();
}
protected static void renderBlockOutline(BlockPos pos, Vec3d color) {
renderBlockOutline(pos, pos, color);
}
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
protected static void renderBlockOutline(BlockPos pos1, BlockPos pos2, Vec3d color) {
GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
RenderGlobal.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
}
//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();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (!BuildModifiers.isEnabled(modifierSettings, 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,192 @@
/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Modified by Requios
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Apr 9, 2014, 11:20:26 PM (GMT)]
*/
package nl.requios.effortlessbuilding.render;
import net.minecraft.client.renderer.OpenGlHelper;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.logging.log4j.Level;
import org.lwjgl.opengl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public final class ShaderHandler {
private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
private static final int VERT = 1;
private static final int FRAG = 2;
private static final String VERT_EXTENSION = ".vert";
private static final String FRAG_EXTENSION = ".frag";
public static int rawColor;
public static int dissolve;
public static void init() {
if(!doUseShaders())
return;
rawColor = createProgram("/assets/effortlessbuilding/shaders/raw_color", FRAG);
dissolve = createProgram("/assets/effortlessbuilding/shaders/dissolve", VERT + FRAG);
}
public static void useShader(int shader, Consumer<Integer> callback) {
if(!doUseShaders())
return;
ARBShaderObjects.glUseProgramObjectARB(shader);
if(shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1iARB(time, ClientProxy.ticksInGame);
if(callback != null)
callback.accept(shader);
}
}
public static void useShader(int shader) {
useShader(shader, null);
}
public static void releaseShader() {
useShader(0);
}
public static boolean doUseShaders() {
return BuildConfig.visuals.useShaders && OpenGlHelper.shadersSupported;
}
private static int createProgram(String s, int sides) {
boolean vert = (sides & VERT) != 0;
boolean frag = (sides & FRAG) != 0;
return createProgram(vert ? s + VERT_EXTENSION : null, frag ? s + FRAG_EXTENSION : null);
}
// Most of the code taken from the LWJGL wiki
// http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL
private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if(vert != null)
vertId = createShader(vert, VERT_ST);
if(frag != null)
fragId = createShader(frag, FRAG_ST);
program = ARBShaderObjects.glCreateProgramObjectARB();
if(program == 0)
return 0;
if(vert != null)
ARBShaderObjects.glAttachObjectARB(program, vertId);
if(frag != null)
ARBShaderObjects.glAttachObjectARB(program, fragId);
ARBShaderObjects.glLinkProgramARB(program);
if(ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
return program;
}
private static int createShader(String filename, int shaderType){
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);
if(shader == 0)
return 0;
ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);
if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE)
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
return shader;
}
catch(Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}
private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}
private static String readFileAsString(String filename) throws Exception {
StringBuilder source = new StringBuilder();
InputStream in = ShaderHandler.class.getResourceAsStream(filename);
Exception exception = null;
BufferedReader reader;
if(in == null)
return "";
try {
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
Exception innerExc= null;
try {
String line;
while((line = reader.readLine()) != null)
source.append(line).append('\n');
} catch(Exception exc) {
exception = exc;
} finally {
try {
reader.close();
} catch(Exception exc) {
innerExc = exc;
}
}
if(innerExc != null)
throw innerExc;
} catch(Exception exc) {
exception = exc;
} finally {
try {
in.close();
} catch(Exception exc) {
if(exception == null)
exception = exc;
else exc.printStackTrace();
}
if(exception != null)
throw exception;
}
return source.toString();
}
}

View File

@@ -1,7 +1,8 @@
key.effortlessbuilding.category=Effortless Building key.effortlessbuilding.category=Effortless Building
key.effortlessbuilding.hud.desc=Open Settings key.effortlessbuilding.hud.desc=Modifier Menu
key.effortlessbuilding.replace.desc=Toggle QuickReplace key.effortlessbuilding.replace.desc=Toggle QuickReplace
key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode
key.effortlessbuilding.mode.desc=Radial Menu
item.effortlessbuilding:randomizer_bag.name=Randomizer Bag item.effortlessbuilding:randomizer_bag.name=Randomizer Bag
item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1 item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1

View File

@@ -0,0 +1,106 @@
#version 120
uniform int time; // Passed in, see ShaderHelper.java
uniform float dissolve; // Passed in via Callback
uniform int highlight;
uniform int red;
uniform vec3 blockpos;
uniform vec3 firstpos;
uniform vec3 secondpos;
uniform sampler2D image;
uniform sampler2D mask;
varying vec4 position;
varying vec3 normal;
void main() {
vec3 pixelposition = floor(position.xyz * 8.0) / 8.0;
vec3 worldpos = blockpos + pixelposition.xyz;
vec2 texcoord = vec2(gl_TexCoord[0]);
vec4 texcolor = texture2D(image, texcoord);
vec4 color = texcolor;
vec3 firstposc = firstpos + 0.51; //center in block
vec3 secondposc = secondpos + 0.5;
//find place in between first and second pos
float firstToSecond = length(secondposc - firstposc);
float place = 0.0;
if (firstToSecond > 0.5) {
float placeFromFirst = length(worldpos - firstposc) / firstToSecond;
float placeFromSecond = length(worldpos - secondposc) / firstToSecond;
place = (placeFromFirst + (1.0 - placeFromSecond)) / 2.0;
} else {
//only one block
}
//find 2d texture coordinate for noise texture based on world position
vec2 maskcoord = vec2(worldpos.y, worldpos.z);
if (abs(normal.y) > 0.5)
maskcoord = vec2(worldpos.x, worldpos.z);
if (abs(normal.z) > 0.5)
maskcoord = vec2(worldpos.x, worldpos.y);
maskcoord /= 20.0;
vec4 maskColor = texture2D(mask, maskcoord);
float maskgs = maskColor.r;
color.rgb *= gl_Color.rgb;
//desaturate
color.rgb *= vec3(0.8);
//add blueish hue
color.rgb += vec3(-0.1, 0.0, 0.2);
//add pulsing blue
float pulse = (sin(time / 5.0) + 1.0) / 2.0;
color.rgb += 0.4 * vec3(-0.5, 0.2, 0.6) * pulse;
//add diagonal highlights
float diagTime = mod(time / 40.0, 1.4) - 0.2;
float diag = smoothstep(diagTime - 0.2, diagTime, place) - smoothstep(diagTime, diagTime + 0.2, place);
color.rgb += 0.2 * diag * vec3(0.0, 0.2, 0.4);
float diagTime2 = mod(time / 70.0, 1.4) - 0.2;
float diag2 = smoothstep(diagTime2 - 0.2, diagTime2, place) - smoothstep(diagTime2, diagTime2 + 0.2, place);
color.rgb += 0.2 * diag2 * vec3(0.0, 0.4, 0.8);
//add edge shading
// vec3 p1;
// //if (firstpos.x < secondpos.x)
//
// vec3 wmf = worldpos - firstposc;
// vec3 wms = worldpos - (secondposc + vec3(0.0, 1.0, 1.0));
// float distToEdge1 = min(length(wmf.xy), length(wmf.xz));
// float distToEdge2 = min(length(wmf.yz), length(wms.xy));
// float distToEdge3 = min(length(wms.xz), length(wms.yz));
// float distToEdge = min(min(distToEdge1, distToEdge2), distToEdge3);
// color.rgb += vec3(0.5 - smoothstep(0, 0.5, distToEdge)) * 0.5;
//add flat shading
if (abs(normal.x) > 0.5)
color.rgb -= 0.0;
if (abs(normal.y) > 0.5)
color.rgb += 0.05;
if (abs(normal.z) > 0.5)
color.rgb -= 0.05;
if (highlight == 1 && dissolve == 0.0) {
color.rgb += vec3(0.0, 0.1, -0.2);
}
if (red == 1) {
color.rgb += vec3(0.4, -0.3, -0.5);
}
color.r = max(0, min(1, color.r));
color.g = max(0, min(1, color.g));
color.b = max(0, min(1, color.b));
if (maskgs * 0.3 + place * 0.7 <= dissolve)
gl_FragColor = vec4(texcolor.rgb, 0.0);
else gl_FragColor = color;
}

View File

@@ -0,0 +1,14 @@
#version 120
varying vec4 position;
varying vec3 normal;
void main() {
gl_Position = ftransform();//gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
//gl_BackColor = gl_Color;
position = gl_Vertex;
normal = gl_Normal;
}

View File

@@ -0,0 +1,15 @@
#version 120
uniform sampler2D bgl_RenderedTexture;
void main() {
vec2 texcoord = vec2(gl_TexCoord[0]);
vec4 color = texture2D(bgl_RenderedTexture, texcoord);
float r = color.b * gl_Color.r;
float g = color.g * gl_Color.g;
float b = color.r * gl_Color.b;
float a = color.a * gl_Color.a;
gl_FragColor = vec4(r, g, b, a);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB