-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix: Bonemeal is no longer infinite in survival mode.
- Loading branch information
Showing
8 changed files
with
504 additions
and
330 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ plugins { | |
} | ||
|
||
group 'no.hyp' | ||
version '1.2.0' | ||
version '1.2.1' | ||
|
||
sourceCompatibility = 1.8 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
436 changes: 109 additions & 327 deletions
436
src/main/java/no/hyp/farmingupgrade/FarmingUpgrade.java
Large diffs are not rendered by default.
Oops, something went wrong.
75 changes: 75 additions & 0 deletions
75
src/main/java/no/hyp/farmingupgrade/FertiliseListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package no.hyp.farmingupgrade; | ||
|
||
import com.google.common.collect.Lists; | ||
import org.bukkit.GameMode; | ||
import org.bukkit.Material; | ||
import org.bukkit.block.Block; | ||
import org.bukkit.block.BlockState; | ||
import org.bukkit.event.EventHandler; | ||
import org.bukkit.event.EventPriority; | ||
import org.bukkit.event.Listener; | ||
import org.bukkit.event.block.BlockFertilizeEvent; | ||
import org.bukkit.inventory.Inventory; | ||
import org.bukkit.inventory.ItemStack; | ||
|
||
import java.util.Collection; | ||
import java.util.Random; | ||
import java.util.function.Consumer; | ||
|
||
final class FertiliseListener implements Listener { | ||
|
||
private final FarmingUpgrade plugin; | ||
|
||
private final Random random; | ||
|
||
public FertiliseListener(FarmingUpgrade plugin, Random random) { | ||
this.plugin = plugin; | ||
this.random = random; | ||
} | ||
|
||
@EventHandler(priority = EventPriority.LOWEST) | ||
public void onFertilise(BlockFertilizeEvent e) { | ||
// Do not handle delegated BlockFertilizeEvents. | ||
if (e instanceof UpgradedBlockFertilizeEvent) { | ||
return; | ||
} | ||
// Only handle if upgraded fertilisation is enabled. | ||
if (!this.plugin.configurationFertiliserUpgrade()) { | ||
return; | ||
} | ||
Block block = e.getBlock(); | ||
// Upgraded fertilisation mechanics are only enabled for specific crops. | ||
if (!this.plugin.fertilisableCrops.containsKey(block.getType())) { | ||
return; | ||
} | ||
// Cancel to let plugin handle event. | ||
e.setCancelled(true); | ||
// Remove a bonemeal if not in creative. | ||
if (e.getPlayer() != null && e.getPlayer().getGameMode() != GameMode.CREATIVE) { | ||
Inventory inventory = e.getPlayer().getInventory(); | ||
int first = inventory.first(Material.BONE_MEAL); | ||
ItemStack item = inventory.getItem(first); | ||
if (item != null) { | ||
item.setAmount(item.getAmount() - 1); | ||
} | ||
} | ||
// Find adjacent fertilisable crops, send a BlockFertilizeEvent for them and apply | ||
// fertiliser if the event is successful. | ||
Collection<Block> fertilisedBlocks = FarmingUpgrade.findAdjacentMaterials(this.plugin.fertilisableCrops.keySet(), block, 1); | ||
for (Block fertilisedBlock : fertilisedBlocks) { | ||
BlockState fertilisedState = fertilisedBlock.getState(); | ||
// Apply fertiliser to the crop state. | ||
Consumer<BlockState> fertiliserFunction = this.plugin.fertilisableCrops.get(fertilisedState.getType()); | ||
fertiliserFunction.accept(fertilisedState); | ||
// Call an event for the fertilised block. | ||
UpgradedBlockFertilizeEvent upgradedEvent = new UpgradedBlockFertilizeEvent(fertilisedBlock, e.getPlayer(), Lists.newArrayList(fertilisedState)); | ||
this.plugin.getServer().getPluginManager().callEvent(upgradedEvent); | ||
// If the event is allowed, apply fertiliser. | ||
if (!upgradedEvent.isCancelled()) { | ||
fertilisedState.update(); | ||
FarmingUpgrade.fertiliseEffect(fertilisedBlock); | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package no.hyp.farmingupgrade; | ||
|
||
import org.bukkit.Location; | ||
import org.bukkit.Particle; | ||
import org.bukkit.block.Block; | ||
import org.bukkit.enchantments.Enchantment; | ||
import org.bukkit.entity.Player; | ||
import org.bukkit.event.EventHandler; | ||
import org.bukkit.event.EventPriority; | ||
import org.bukkit.event.Listener; | ||
import org.bukkit.event.block.BlockBreakEvent; | ||
import org.bukkit.inventory.ItemStack; | ||
import org.bukkit.util.Vector; | ||
|
||
import java.util.Random; | ||
import java.util.Set; | ||
|
||
final class HarvestListener implements Listener { | ||
|
||
private final FarmingUpgrade plugin; | ||
|
||
private final Random random; | ||
|
||
public HarvestListener(FarmingUpgrade plugin, Random random) { | ||
this.plugin = plugin; | ||
this.random = random; | ||
} | ||
|
||
/** | ||
* If a player breaks a crop with a hoe, handle this event manually. Find the adjacent crops | ||
* and call custom UpgradedBlockBreakEvents on the to give other plugins a chance to catch them. | ||
* | ||
* Since this is a mechanic the event should be caught and cancelled as early as possible (LOWEST priority). | ||
* Then we can dispatch new events that we can control the outcome of ourselves. | ||
*/ | ||
@EventHandler(priority = EventPriority.LOWEST) | ||
public void onFarm(BlockBreakEvent e) { | ||
if (!this.plugin.configurationHoeUpgrade()) { | ||
return; | ||
} | ||
// Do not handle events that are called by FarmingUpgrade. | ||
if (e instanceof UpgradedBlockBreakEvent) { | ||
return; | ||
} | ||
Player player = e.getPlayer(); | ||
Block crop = e.getBlock(); | ||
// Handle breaking of crops. | ||
if (!this.plugin.harvestableCrops.containsKey(crop.getType())) { | ||
return; | ||
} | ||
ItemStack tool = player.getInventory().getItemInMainHand(); | ||
// If broken by a hoe, all crops within range are harvested and automatically replanted. | ||
if (!this.plugin.tools.containsKey(tool.getType())) { | ||
return; | ||
} | ||
e.setCancelled(true); | ||
Vector direction = player.getLocation().getDirection(); | ||
//direction.add(new Vector(0.0, -direction.getY(), 0.0)).multiply(1.0 / direction.length()); | ||
Location location = player.getEyeLocation(); | ||
location.add(direction.multiply(1.5)); | ||
player.getWorld().spawnParticle(Particle.SWEEP_ATTACK, location, 1); | ||
// Calculate the radius of the hoe sweep. | ||
// Radius is affected by hoe material and the Efficiency enchantment (1 radius per 2 levels). | ||
int range; | ||
if (this.plugin.configurationHoeRange()) { | ||
if (this.plugin.configurationHoeEfficiency()) { | ||
range = Math.min(7, this.plugin.tools.get(tool.getType()) + tool.getEnchantmentLevel(Enchantment.DIG_SPEED) / 2); | ||
} else { | ||
range = Math.min(7, this.plugin.tools.get(tool.getType())); | ||
} | ||
} else { | ||
range = 0; | ||
} | ||
// Get the adjacent crops in range. | ||
Set<Block> adjacentCrops = FarmingUpgrade.findAdjacentMaterials(this.plugin.harvestableCrops.keySet(), crop, range); | ||
// For every crop block, simulate a BlockBreakEvent for other plugins to react to. | ||
boolean replant = this.plugin.configurationHoeReplant(); | ||
boolean unbreaking = this.plugin.configurationHoeUnbreaking(); | ||
boolean collect = this.plugin.configurationHoeCollect(); | ||
boolean harvest = this.plugin.configurationHoeHarvest(); | ||
for (Block adjacentCrop : adjacentCrops) { | ||
FarmingUpgrade.harvestCrop(this.random, player, adjacentCrop, tool, replant, unbreaking, collect, harvest, this.plugin.harvestableCrops.get(adjacentCrop.getType())); | ||
} | ||
} | ||
|
||
} |
159 changes: 159 additions & 0 deletions
159
src/main/java/no/hyp/farmingupgrade/HydrationListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package no.hyp.farmingupgrade; | ||
|
||
import org.bukkit.Material; | ||
import org.bukkit.block.Block; | ||
import org.bukkit.event.EventHandler; | ||
import org.bukkit.event.EventPriority; | ||
import org.bukkit.event.Listener; | ||
import org.bukkit.event.block.Action; | ||
import org.bukkit.event.block.BlockFadeEvent; | ||
import org.bukkit.event.block.BlockGrowEvent; | ||
import org.bukkit.event.block.MoistureChangeEvent; | ||
import org.bukkit.event.player.PlayerInteractEvent; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
final class HydrationListener implements Listener { | ||
|
||
private final FarmingUpgrade plugin; | ||
|
||
/** | ||
* When a player tramples farmland, Minecraft calls a PlayerInteractEvent, and then | ||
* a BlockFadeEvent. Minecraft also calls FadeEvent when a Farmland is turning to | ||
* Dirt from dehydration. To distinguish between trampling and drying, store the | ||
* block that is trampled in InteractEvent here and check if it equal in the FadeEvent. | ||
*/ | ||
private Block trampledFarmland; | ||
|
||
public HydrationListener(FarmingUpgrade plugin) { | ||
this.plugin = plugin; | ||
} | ||
|
||
/** | ||
* Use this event to detect if the next BlockFadeEvent is caused by trampling. | ||
* In that case, the hydration listener should not handle it. | ||
* | ||
* @param e | ||
*/ | ||
@EventHandler(priority = EventPriority.LOWEST) | ||
public void onFarmlandTrample(@NotNull PlayerInteractEvent e) { | ||
// Do not handle events that are delegated by FarmingUpgrade. | ||
if (e instanceof UpgradedPlayerInteractEvent) { | ||
return; | ||
} | ||
// Check that this is a Farmland trample event. | ||
Block farmland = e.getClickedBlock(); | ||
boolean trample = farmland != null && farmland.getType() == Material.FARMLAND && e.getAction() == Action.PHYSICAL; | ||
if (!trample) { | ||
return; | ||
} | ||
// Store the farmland so the hydration listener does not handle it. | ||
this.trampledFarmland = farmland; | ||
} | ||
|
||
/** | ||
* A BlockFadeEvent is called when Minecraft wants to turn a Farmland block with a moisture level of 0 | ||
* into Dirt. | ||
* | ||
* It is also called after a PlayerInteractEvent, after a player tramples (jumps on) a | ||
* Farmland block. This happens if upgraded trample mechanics is not enabled. | ||
* | ||
* Trample is handled elsewhere, so only handle drying here. | ||
* | ||
* @param e The event. | ||
*/ | ||
@EventHandler(priority = EventPriority.LOWEST) | ||
public void onFarmlandDry(BlockFadeEvent e) { | ||
// Do not handle events that are delegated by FarmingUpgrade. | ||
if (e instanceof UpgradedBlockFadeEvent) { | ||
return; | ||
} | ||
// Check that this is a Farmland dry or trample event. | ||
Block farmland = e.getBlock(); | ||
if (farmland.getType() != Material.FARMLAND) { | ||
return; | ||
} | ||
// Check if this block was trampled or if it is drying up. | ||
// If this block is drying, apply upgraded hydration mechanics if they are enabled. | ||
// If the block is trampled, let Minecraft handle it. | ||
if (!farmland.equals(this.trampledFarmland)) { | ||
// If upgraded hydration is enabled, cancel the event and handle it manually. | ||
// Otherwise, let Minecraft handle the event as normal. | ||
if (this.plugin.configurationHydrationUpgrade()) { | ||
e.setCancelled(true); | ||
int range = this.plugin.configurationHydrationRange(); | ||
int depth = this.plugin.configurationHydrationDepth(); | ||
int height = this.plugin.configurationHydrationHeight(); | ||
boolean dry = this.plugin.configurationHydrationDry(); | ||
FarmingUpgrade.farmlandUpgradedChangeMoisture(farmland, range, depth, height, dry); | ||
} | ||
} | ||
// The trampled farmland check is no longer needed after handling the event. | ||
this.trampledFarmland = null; | ||
} | ||
|
||
/** | ||
* MoistureChangeEvent is called when Minecraft wants to change the moisture level of | ||
* Farmland. Minecraft wants to dehydrate or dry (turn to Dirt) Farmland outside the | ||
* Vanilla water range, and hydrate Farmland within the Vanilla water range. | ||
* | ||
* For blocks outside the Vanilla water range, but within the upgraded water range, cancel this | ||
* event and hydrate the Farmland instead. Remember to also catch BlockFadeEvent for Farmland with the | ||
* lowest humidity. | ||
* | ||
* For blocks inside the Vanilla water range, but outside the upgraded water range, dehydrate | ||
* the Farmland instead. For fully hydrated Farmland, no event will be thrown. Use something | ||
* like BlockGrowEvent to create events for fully hydrated Farmland. | ||
* | ||
* @param e | ||
*/ | ||
@EventHandler(priority = EventPriority.LOWEST) | ||
public void onFarmlandMoistureChange(MoistureChangeEvent e) { | ||
if (!this.plugin.configurationHydrationUpgrade()) { | ||
return; | ||
} | ||
// Do not handle events that are called by FarmingUpgrade. | ||
if (e instanceof UpgradedMoistureChangeEvent) { | ||
return; | ||
} | ||
Block farmland = e.getBlock(); | ||
if (farmland.getType() != Material.FARMLAND) { | ||
return; | ||
} | ||
e.setCancelled(true); | ||
int range = this.plugin.configurationHydrationRange(); | ||
int depth = this.plugin.configurationHydrationDepth(); | ||
int height = this.plugin.configurationHydrationHeight(); | ||
boolean dry = this.plugin.configurationHydrationDry(); | ||
FarmingUpgrade.farmlandUpgradedChangeMoisture(farmland, range, depth, height, dry); | ||
} | ||
|
||
/** | ||
* BlockGrowEvent is called when a crop grows. | ||
* | ||
* Minecraft does not send any events for fully hydrated Farmland within the Vanilla water range. | ||
* Use BlockGrowEvents to create events for fully hydrated Farmland to use upgraded hydration mechanics. | ||
* | ||
* Minecraft does not dry Farmland into Dirt if there is a crop on it, and thus do not send | ||
* any events either. Use the grow event to update the Farmland moisture. | ||
* | ||
* @param e | ||
*/ | ||
@EventHandler(priority = EventPriority.MONITOR) | ||
public void onCropGrow(BlockGrowEvent e) { | ||
if (!this.plugin.configurationHydrationUpgrade()) { | ||
return; | ||
} | ||
if (e.isCancelled()) { | ||
return; | ||
} | ||
Block farmland = e.getBlock().getRelative(0, -1, 0); | ||
if (farmland.getType() == Material.FARMLAND) { | ||
int range = this.plugin.configurationHydrationRange(); | ||
int depth = this.plugin.configurationHydrationDepth(); | ||
int height = this.plugin.configurationHydrationHeight(); | ||
boolean dry = this.plugin.configurationHydrationDry(); | ||
FarmingUpgrade.farmlandUpgradedChangeMoisture(farmland, range, depth, height, dry); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.