2020-04-15 22:35:14 +00:00
|
|
|
/*
|
2022-01-01 19:03:05 +00:00
|
|
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
2020-04-15 22:35:14 +00:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*
|
|
|
|
* @author GeyserMC
|
|
|
|
* @link https://github.com/GeyserMC/Geyser
|
|
|
|
*/
|
|
|
|
|
2021-11-20 23:29:46 +00:00
|
|
|
package org.geysermc.geyser.entity.type;
|
2020-04-15 22:33:16 +00:00
|
|
|
|
2021-11-18 03:02:38 +00:00
|
|
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
2020-04-15 22:33:16 +00:00
|
|
|
import com.nukkitx.math.vector.Vector3f;
|
2020-06-23 00:11:09 +00:00
|
|
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
2021-02-19 16:12:36 +00:00
|
|
|
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
2021-11-19 01:44:03 +00:00
|
|
|
import lombok.Getter;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
|
|
|
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
2022-05-31 18:25:15 +00:00
|
|
|
import org.geysermc.geyser.level.block.BlockPositionIterator;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.level.block.BlockStateValues;
|
2022-05-31 18:25:15 +00:00
|
|
|
import org.geysermc.geyser.level.physics.BoundingBox;
|
2021-11-20 21:34:30 +00:00
|
|
|
import org.geysermc.geyser.registry.BlockRegistries;
|
2022-05-31 18:25:15 +00:00
|
|
|
import org.geysermc.geyser.session.GeyserSession;
|
|
|
|
import org.geysermc.geyser.translator.collision.BlockCollision;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.util.BlockUtils;
|
2020-04-15 22:33:16 +00:00
|
|
|
|
2021-11-18 03:02:38 +00:00
|
|
|
import java.util.UUID;
|
2021-02-19 16:12:36 +00:00
|
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
|
|
|
|
|
|
public class FishingHookEntity extends ThrowableEntity {
|
|
|
|
|
|
|
|
private boolean hooked = false;
|
2021-11-19 01:44:03 +00:00
|
|
|
private boolean inWater = false;
|
2021-02-19 16:12:36 +00:00
|
|
|
|
2021-11-19 01:44:03 +00:00
|
|
|
@Getter
|
2021-12-20 00:15:53 +00:00
|
|
|
private final long bedrockOwnerId;
|
2021-11-19 01:44:03 +00:00
|
|
|
@Getter
|
|
|
|
private long bedrockTargetId;
|
2021-02-19 16:12:36 +00:00
|
|
|
|
2021-11-19 01:44:03 +00:00
|
|
|
private final BoundingBox boundingBox;
|
2021-02-19 16:12:36 +00:00
|
|
|
|
2022-05-24 23:16:40 +00:00
|
|
|
public FishingHookEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, PlayerEntity owner) {
|
2021-11-18 03:02:38 +00:00
|
|
|
super(session, entityId, geyserId, uuid, EntityDefinitions.FISHING_BOBBER, position, motion, yaw, pitch, 0f);
|
2020-05-05 15:48:01 +00:00
|
|
|
|
2021-02-19 16:12:36 +00:00
|
|
|
this.boundingBox = new BoundingBox(0.125, 0.125, 0.125, 0.25, 0.25, 0.25);
|
2020-05-17 04:57:18 +00:00
|
|
|
|
2021-02-19 16:12:36 +00:00
|
|
|
// In Java, the splash sound depends on the entity's velocity, but in Bedrock the volume doesn't change.
|
|
|
|
// This splash can be confused with the sound from catching a fish. This silences the splash from Bedrock,
|
|
|
|
// so that it can be handled by moveAbsoluteImmediate.
|
2021-11-19 01:44:03 +00:00
|
|
|
setBoundingBoxHeight(128);
|
2021-02-19 16:12:36 +00:00
|
|
|
|
2021-12-20 00:15:53 +00:00
|
|
|
this.bedrockOwnerId = owner.getGeyserId();
|
|
|
|
this.dirtyMetadata.put(EntityData.OWNER_EID, this.bedrockOwnerId);
|
2021-11-18 03:02:38 +00:00
|
|
|
}
|
|
|
|
|
2021-11-20 19:25:21 +00:00
|
|
|
public void setHookedEntity(IntEntityMetadata entityMetadata) {
|
|
|
|
int hookedEntityId = entityMetadata.getPrimitiveValue() - 1;
|
2021-12-18 16:43:57 +00:00
|
|
|
Entity entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
|
2021-11-18 03:02:38 +00:00
|
|
|
if (entity != null) {
|
2021-11-19 01:44:03 +00:00
|
|
|
bedrockTargetId = entity.getGeyserId();
|
|
|
|
dirtyMetadata.put(EntityData.TARGET_EID, bedrockTargetId);
|
2021-11-18 03:02:38 +00:00
|
|
|
hooked = true;
|
|
|
|
} else {
|
|
|
|
hooked = false;
|
|
|
|
}
|
2020-05-11 05:09:16 +00:00
|
|
|
}
|
2021-02-19 16:12:36 +00:00
|
|
|
|
|
|
|
@Override
|
2021-11-18 03:02:38 +00:00
|
|
|
protected void moveAbsoluteImmediate(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
2021-02-19 16:12:36 +00:00
|
|
|
boundingBox.setMiddleX(position.getX());
|
|
|
|
boundingBox.setMiddleY(position.getY() + boundingBox.getSizeY() / 2);
|
|
|
|
boundingBox.setMiddleZ(position.getZ());
|
|
|
|
|
|
|
|
boolean touchingWater = false;
|
|
|
|
boolean collided = false;
|
2021-09-26 14:16:22 +00:00
|
|
|
for (BlockPositionIterator iter = session.getCollisionManager().collidableBlocksIterator(boundingBox); iter.hasNext(); iter.next()) {
|
2021-11-20 21:34:30 +00:00
|
|
|
int blockID = session.getGeyser().getWorldManager().getBlockAt(session, iter.getX(), iter.getY(), iter.getZ());
|
2021-09-26 14:16:22 +00:00
|
|
|
BlockCollision blockCollision = BlockUtils.getCollision(blockID);
|
2021-07-31 02:35:13 +00:00
|
|
|
if (blockCollision != null) {
|
2021-09-26 14:16:22 +00:00
|
|
|
if (blockCollision.checkIntersection(iter.getX(), iter.getY(), iter.getZ(), boundingBox)) {
|
2021-07-31 02:35:13 +00:00
|
|
|
// TODO Push bounding box out of collision to improve movement
|
|
|
|
collided = true;
|
|
|
|
}
|
2021-03-21 15:31:09 +00:00
|
|
|
}
|
2021-02-19 16:12:36 +00:00
|
|
|
|
2022-07-03 01:17:14 +00:00
|
|
|
double waterHeight = BlockStateValues.getWaterHeight(blockID);
|
|
|
|
if (waterHeight != -1 && position.getY() <= (iter.getY() + waterHeight)) {
|
|
|
|
touchingWater = true;
|
2021-02-19 16:12:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!inWater && touchingWater) {
|
|
|
|
sendSplashSound(session);
|
|
|
|
}
|
|
|
|
inWater = touchingWater;
|
|
|
|
|
|
|
|
if (!collided) {
|
2021-11-18 03:02:38 +00:00
|
|
|
super.moveAbsoluteImmediate(position, yaw, pitch, headYaw, isOnGround, teleported);
|
2021-02-19 16:12:36 +00:00
|
|
|
} else {
|
2021-11-18 03:02:38 +00:00
|
|
|
super.moveAbsoluteImmediate(this.position, yaw, pitch, headYaw, true, true);
|
2021-02-19 16:12:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-22 19:52:26 +00:00
|
|
|
private void sendSplashSound(GeyserSession session) {
|
2022-05-31 18:25:15 +00:00
|
|
|
if (!silent) {
|
2021-02-19 16:12:36 +00:00
|
|
|
float volume = (float) (0.2f * Math.sqrt(0.2 * (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) + motion.getY() * motion.getY()));
|
|
|
|
if (volume > 1) {
|
|
|
|
volume = 1;
|
|
|
|
}
|
|
|
|
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
|
|
|
playSoundPacket.setSound("random.splash");
|
|
|
|
playSoundPacket.setPosition(position);
|
|
|
|
playSoundPacket.setVolume(volume);
|
|
|
|
playSoundPacket.setPitch(1f + ThreadLocalRandom.current().nextFloat() * 0.3f);
|
|
|
|
session.sendUpstreamPacket(playSoundPacket);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-11-18 03:02:38 +00:00
|
|
|
public void tick() {
|
|
|
|
if (hooked || !isInAir() && !isInWater() || isOnGround()) {
|
2021-02-19 16:12:36 +00:00
|
|
|
motion = Vector3f.ZERO;
|
|
|
|
return;
|
|
|
|
}
|
2021-11-18 03:02:38 +00:00
|
|
|
float gravity = getGravity();
|
2021-02-19 16:12:36 +00:00
|
|
|
motion = motion.down(gravity);
|
|
|
|
|
2022-04-23 18:57:32 +00:00
|
|
|
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
2021-02-19 16:12:36 +00:00
|
|
|
|
2021-11-18 03:02:38 +00:00
|
|
|
float drag = getDrag();
|
2021-02-19 16:12:36 +00:00
|
|
|
motion = motion.mul(drag);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-11-18 03:02:38 +00:00
|
|
|
protected float getGravity() {
|
2022-04-23 18:57:32 +00:00
|
|
|
if (!isInWater() && !isOnGround()) {
|
2021-02-19 16:12:36 +00:00
|
|
|
return 0.03f;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return true if this entity is currently in air.
|
|
|
|
*/
|
2021-11-18 03:02:38 +00:00
|
|
|
protected boolean isInAir() {
|
2021-11-20 21:34:30 +00:00
|
|
|
int block = session.getGeyser().getWorldManager().getBlockAt(session, position.toInt());
|
2021-07-13 01:19:40 +00:00
|
|
|
return block == BlockStateValues.JAVA_AIR_ID;
|
2021-02-19 16:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-11-18 03:02:38 +00:00
|
|
|
protected float getDrag() {
|
2021-02-19 16:12:36 +00:00
|
|
|
return 0.92f;
|
|
|
|
}
|
2020-04-15 22:33:16 +00:00
|
|
|
}
|