mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
Add a hook for farmland watering (#4891)
This commit is contained in:
1 parent
72bc39d831
commit
a67cce2f91
11 files changed
+635
No files matched your search
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.IWorldReaderBase;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraftforge.common.ticket.AABBTicket;
|
||||
import net.minecraftforge.common.ticket.ChunkTicketManager;
|
||||
import net.minecraftforge.common.ticket.MultiTicketManager;
|
||||
import net.minecraftforge.common.ticket.SimpleTicket;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class FarmlandWaterManager
|
||||
{
|
||||
private static final Int2ObjectMap<Map<ChunkPos, ChunkTicketManager<Vec3d>>> customWaterHandler = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Adds a custom ticket.
|
||||
* Use {@link #addAABBTicket(World, AxisAlignedBB)} if you just need a ticket that can water a certain area.
|
||||
* <br>
|
||||
* If you don't want to water the region anymore, call {@link SimpleTicket#invalidate()}. Also call this
|
||||
* when the region this is unloaded (e.g. your TE is unloaded or the block is removed), and validate once it is loaded
|
||||
* @param world The world where the region should be marked. Only server-side worlds are allowed
|
||||
* @param ticket Your ticket you want to have registered
|
||||
* @param chunkPoses The chunkPoses where the ticket is located
|
||||
* @return The ticket for your requested region.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static<T extends SimpleTicket<Vec3d>> T addCustomTicket(World world, T ticket, ChunkPos... chunkPoses)
|
||||
{
|
||||
Preconditions.checkArgument(!world.isRemote, "Water region is only determined server-side");
|
||||
Preconditions.checkArgument(chunkPoses.length > 0, "Need at least one chunk pos");
|
||||
Map<ChunkPos, ChunkTicketManager<Vec3d>> ticketMap = customWaterHandler.computeIfAbsent(world.getDimension().getType().getId(), id -> new HashMap<>());
|
||||
if (chunkPoses.length == 1)
|
||||
{
|
||||
ticket.setBackend(ticketMap.computeIfAbsent(chunkPoses[0], ChunkTicketManager::new));
|
||||
}
|
||||
else
|
||||
{
|
||||
ChunkTicketManager<Vec3d>[] tickets = new ChunkTicketManager[chunkPoses.length];
|
||||
for (int i = 0; i < chunkPoses.length; i++)
|
||||
tickets[i] = ticketMap.computeIfAbsent(chunkPoses[i], ChunkTicketManager::new);
|
||||
ticket.setBackend(new MultiTicketManager<>(tickets));
|
||||
}
|
||||
ticket.validate();
|
||||
return ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to add a ticket that is backed by an AABB.
|
||||
* <br>
|
||||
* If you don't want to water the region anymore, call {@link SimpleTicket#invalidate()}. Also call this
|
||||
* when the region this is unloaded (e.g. your TE is unloaded or the block is removed), and validate once it is loaded
|
||||
* <br>
|
||||
* The AABB in the ticket is immutable
|
||||
* @param world The world where the region should be marked. Only server-side worlds are allowed
|
||||
* @param aabb The region where blocks should be watered
|
||||
* @return The ticket for your requested region.
|
||||
*/
|
||||
public static AABBTicket addAABBTicket(World world, AxisAlignedBB aabb)
|
||||
{
|
||||
//First calculate all chunks the aabb is in
|
||||
ChunkPos leftUp = new ChunkPos(((int) aabb.minX) >> 4, ((int) aabb.minZ) >> 4);
|
||||
ChunkPos rightDown = new ChunkPos(((int) aabb.maxX) >> 4, ((int) aabb.maxZ) >> 4);
|
||||
Set<ChunkPos> posSet = new HashSet<>();
|
||||
for (int x = leftUp.x; x <= rightDown.x; x++)
|
||||
{
|
||||
for (int z = leftUp.z; z <= rightDown.z; z++)
|
||||
{
|
||||
posSet.add(new ChunkPos(x, z));
|
||||
}
|
||||
}
|
||||
return addCustomTicket(world, new AABBTicket(aabb), posSet.toArray(new ChunkPos[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a block is in a region that is watered by blocks. This does not check vanilla water, see {@link net.minecraft.block.BlockFarmland#hasWater(World, BlockPos)}
|
||||
* @return true if there is a ticket with an AABB that includes your block
|
||||
*/
|
||||
public static boolean hasBlockWaterTicket(IWorldReaderBase world, BlockPos pos)
|
||||
{
|
||||
ChunkTicketManager<Vec3d> ticketManager = getTicketManager(new ChunkPos(pos.getX() >> 4, pos.getZ() >> 4), world);
|
||||
if (ticketManager != null)
|
||||
{
|
||||
Vec3d posAsVec3d = new Vec3d(pos);
|
||||
for (SimpleTicket<Vec3d> ticket : ticketManager.getTickets()) {
|
||||
if (ticket.matches(posAsVec3d))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void removeTickets(IChunk chunk)
|
||||
{
|
||||
ChunkTicketManager<Vec3d> ticketManager = getTicketManager(chunk.getPos(), chunk.getWorldForge());
|
||||
if (ticketManager != null)
|
||||
{
|
||||
for (SimpleTicket<Vec3d> ticket : ticketManager.getTickets())
|
||||
{
|
||||
ticket.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ChunkTicketManager<Vec3d> getTicketManager(ChunkPos pos, IWorldReaderBase world) {
|
||||
Preconditions.checkArgument(!world.isRemote(), "Water region is only determined server-side");
|
||||
Map<ChunkPos, ChunkTicketManager<Vec3d>> ticketMap = customWaterHandler.get(world.getDimension().getType().getId());
|
||||
if (ticketMap == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ticketMap.get(pos);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.client.CloudRenderer;
|
||||
import net.minecraftforge.common.util.FakePlayerFactory;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -80,5 +81,12 @@ public class ForgeInternalHandler
|
||||
if (event.phase == Phase.END)
|
||||
CloudRenderer.updateCloudSettings();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onChunkUnload(ChunkEvent.Unload event)
|
||||
{
|
||||
if (!event.getWorld().isRemote())
|
||||
FarmlandWaterManager.removeTickets(event.getChunk());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.ticket;
|
||||
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AABBTicket extends SimpleTicket<Vec3d>
|
||||
{
|
||||
@Nonnull
|
||||
public final AxisAlignedBB axisAlignedBB;
|
||||
|
||||
public AABBTicket(@Nonnull AxisAlignedBB axisAlignedBB)
|
||||
{
|
||||
this.axisAlignedBB = axisAlignedBB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Vec3d toMatch)
|
||||
{
|
||||
return this.axisAlignedBB.contains(toMatch);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.ticket;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class ChunkTicketManager<T> implements ITicketGetter<T>
|
||||
{
|
||||
private final Set<SimpleTicket<T>> tickets = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
public final ChunkPos pos;
|
||||
|
||||
public ChunkTicketManager(ChunkPos pos)
|
||||
{
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(SimpleTicket<T> ticket)
|
||||
{
|
||||
this.tickets.add(ticket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(SimpleTicket<T> ticket)
|
||||
{
|
||||
this.tickets.remove(ticket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimpleTicket<T>> getTickets()
|
||||
{
|
||||
return tickets;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.ticket;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ITicketGetter<T> extends ITicketManager<T>
|
||||
{
|
||||
Collection<SimpleTicket<T>> getTickets();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.ticket;
|
||||
|
||||
public interface ITicketManager<T>
|
||||
{
|
||||
void add(SimpleTicket<T> ticket);
|
||||
|
||||
void remove(SimpleTicket<T> ticket);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.ticket;
|
||||
|
||||
public class MultiTicketManager<T> implements ITicketManager<T>
|
||||
{
|
||||
private final ITicketGetter<T>[] ticketManagers;
|
||||
|
||||
@SafeVarargs
|
||||
public MultiTicketManager(ITicketGetter<T>... ticketManagers)
|
||||
{
|
||||
this.ticketManagers = ticketManagers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(SimpleTicket<T> ticket)
|
||||
{
|
||||
for (ITicketGetter<T> manager : ticketManagers)
|
||||
manager.add(ticket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(SimpleTicket<T> ticket)
|
||||
{
|
||||
for (ITicketGetter<T> manager : ticketManagers)
|
||||
manager.remove(ticket);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2018.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.ticket;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Common class for a simple ticket based system.
|
||||
* @param <T> The type that will be used to check if your ticket matches
|
||||
*/
|
||||
public abstract class SimpleTicket<T>
|
||||
{
|
||||
@Nullable
|
||||
private ITicketManager<T> manager;
|
||||
protected boolean isValid = false;
|
||||
|
||||
/**
|
||||
* Internal method that sets the collection from the managing system.
|
||||
* <br>
|
||||
* Should <b>not</b> be called if you just want to register a ticket to a system like the {@link net.minecraftforge.common.FarmlandWaterManager}
|
||||
*/
|
||||
public final void setBackend(@Nonnull ITicketManager<T> ticketManager)
|
||||
{
|
||||
Preconditions.checkState(this.manager == null, "Ticket is already registered to a managing system");
|
||||
this.manager = ticketManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if your ticket is still registered in the system.
|
||||
*/
|
||||
public boolean isValid()
|
||||
{
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the ticket from the managing system.
|
||||
* After this call, any calls to {@link #isValid()} should return false unless it is registered again using {@link #validate()}
|
||||
*/
|
||||
public void invalidate()
|
||||
{
|
||||
Preconditions.checkState(this.manager != null, "Ticket is not registered to a managing system");
|
||||
if (this.isValid())
|
||||
{
|
||||
this.manager.remove(this);
|
||||
}
|
||||
this.isValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-adds your ticket to the system.
|
||||
*/
|
||||
public void validate()
|
||||
{
|
||||
Preconditions.checkState(this.manager != null, "Ticket is not registered to a managing system");
|
||||
if (!this.isValid())
|
||||
{
|
||||
this.manager.add(this);
|
||||
}
|
||||
this.isValid = true;
|
||||
}
|
||||
|
||||
public abstract boolean matches(T toMatch);
|
||||
}
|
||||
Reference in new issue
Block a user