use of org.terasology.physics.HitResult in project Terasology by MovingBlocks.
the class CameraTargetSystem method update.
public void update(float delta) {
// Repair lost target
// TODO: Improvements to temporary chunk handling will remove the need for this
boolean lostTarget = false;
updateTarget();
if (!target.exists()) {
targetBlockPos = null;
lostTarget = true;
}
HitResult hitInfo = physics.rayTrace(new Vector3f(localPlayer.getViewPosition()), new Vector3f(localPlayer.getViewDirection()), targetDistance, filter);
updateFocalDistance(hitInfo, delta);
Vector3i newBlockPos = null;
EntityRef newTarget = EntityRef.NULL;
if (hitInfo.isHit()) {
newTarget = hitInfo.getEntity();
hitPosition = hitInfo.getHitPoint();
hitNormal = hitInfo.getHitNormal();
if (hitInfo.isWorldHit()) {
newBlockPos = new Vector3i(hitInfo.getBlockPosition());
}
}
if (!Objects.equal(target, newTarget) || lostTarget) {
EntityRef oldTarget = target;
oldTarget.send(new CameraOutEvent());
newTarget.send(new CameraOverEvent());
localPlayer.getCharacterEntity().send(new CameraTargetChangedEvent(oldTarget, newTarget));
// Set isBlock to false if the hit-entity does not have a BlockComponent
isBlock = !(isTargetAvailable() && !newTarget.hasComponent(BlockComponent.class));
}
target = newTarget;
targetBlockPos = newBlockPos;
}
use of org.terasology.physics.HitResult in project Terasology by MovingBlocks.
the class CharacterSystem method isPredictionOfEventCorrect.
private boolean isPredictionOfEventCorrect(EntityRef character, ActivationRequest event) {
CharacterComponent characterComponent = character.getComponent(CharacterComponent.class);
EntityRef camera = GazeAuthoritySystem.getGazeEntityForCharacter(character);
LocationComponent location = camera.getComponent(LocationComponent.class);
Vector3f direction = location.getWorldDirection();
if (!(vectorsAreAboutEqual(event.getDirection(), direction))) {
logger.error("Direction at client {} was different than direction at server {}", event.getDirection(), direction);
}
// Assume the exact same value in case there are rounding mistakes:
direction = event.getDirection();
Vector3f originPos = location.getWorldPosition();
if (!(vectorsAreAboutEqual(event.getOrigin(), originPos))) {
String msg = "Player {} seems to have cheated: It stated that it performed an action from {} but the predicted position is {}";
logger.info(msg, getPlayerNameFromCharacter(character), event.getOrigin(), originPos);
return false;
}
if (event.isOwnedEntityUsage()) {
if (!event.getUsedOwnedEntity().exists()) {
String msg = "Denied activation attempt by {} since the used entity does not exist on the authority";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
if (!networkSystem.getOwnerEntity(event.getUsedOwnedEntity()).equals(networkSystem.getOwnerEntity(character))) {
String msg = "Denied activation attempt by {} since it does not own the entity at the authority";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
} else {
// check for cheats so that data can later be trusted:
if (event.getUsedOwnedEntity().exists()) {
String msg = "Denied activation attempt by {} since it is not properly marked as owned entity usage";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
}
if (event.isEventWithTarget()) {
if (!event.getTarget().exists()) {
String msg = "Denied activation attempt by {} since the target does not exist on the authority";
logger.info(msg, getPlayerNameFromCharacter(character));
// can happen if target existed on client
return false;
}
HitResult result = physics.rayTrace(originPos, direction, characterComponent.interactionRange, Sets.newHashSet(character), DEFAULTPHYSICSFILTER);
if (!result.isHit()) {
String msg = "Denied activation attempt by {} since at the authority there was nothing to activate at that place";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
EntityRef hitEntity = result.getEntity();
if (!hitEntity.equals(event.getTarget())) {
/**
* Tip for debugging this issue: Obtain the network id of hit entity and search it in both client and
* server entity dump. When certain fields don't get replicated, then wrong entity might get hin in the
* hit test.
*/
String msg = "Denied activation attempt by {} since at the authority another entity would have been activated";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
if (!(vectorsAreAboutEqual(event.getHitPosition(), result.getHitPoint()))) {
String msg = "Denied activation attempt by {} since at the authority the object got hit at a differnt position";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
} else {
// In order to trust the data later we need to verify it even if it should be correct if no one cheats:
if (event.getTarget().exists()) {
String msg = "Denied activation attempt by {} since the event was not properly labeled as having a target";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
if (!(vectorsAreAboutEqual(event.getHitPosition(), originPos))) {
String msg = "Denied activation attempt by {} since the event was not properly labeled as having a hit postion";
logger.info(msg, getPlayerNameFromCharacter(character));
return false;
}
}
return true;
}
use of org.terasology.physics.HitResult in project Terasology by MovingBlocks.
the class LocalPlayer method activateTargetOrOwnedEntity.
/**
* @param usedOwnedEntity if it does not exist it is not an item usage.
* @return true if an activation request got sent. Returns always true if usedItem exists.
*/
private boolean activateTargetOrOwnedEntity(EntityRef usedOwnedEntity) {
EntityRef character = getCharacterEntity();
CharacterComponent characterComponent = character.getComponent(CharacterComponent.class);
Vector3f direction = getViewDirection();
Vector3f originPos = getViewPosition();
boolean ownedEntityUsage = usedOwnedEntity.exists();
int activationId = nextActivationId++;
Physics physics = CoreRegistry.get(Physics.class);
HitResult result = physics.rayTrace(originPos, direction, characterComponent.interactionRange, Sets.newHashSet(character), CharacterSystem.DEFAULTPHYSICSFILTER);
boolean eventWithTarget = result.isHit();
if (eventWithTarget) {
EntityRef activatedObject = usedOwnedEntity.exists() ? usedOwnedEntity : result.getEntity();
activatedObject.send(new ActivationPredicted(character, result.getEntity(), originPos, direction, result.getHitPoint(), result.getHitNormal(), activationId));
character.send(new ActivationRequest(character, ownedEntityUsage, usedOwnedEntity, eventWithTarget, result.getEntity(), originPos, direction, result.getHitPoint(), result.getHitNormal(), activationId));
return true;
} else if (ownedEntityUsage) {
usedOwnedEntity.send(new ActivationPredicted(character, EntityRef.NULL, originPos, direction, originPos, new Vector3f(), activationId));
character.send(new ActivationRequest(character, ownedEntityUsage, usedOwnedEntity, eventWithTarget, EntityRef.NULL, originPos, direction, originPos, new Vector3f(), activationId));
return true;
}
return false;
}
use of org.terasology.physics.HitResult in project Terasology by MovingBlocks.
the class ArrowAction method onActivate.
@ReceiveEvent
public void onActivate(ActivateEvent event, EntityRef entity, ArrowActionComponent arrowActionComponent) {
if (time.getGameTime() > lastTime + 1.0f / arrowActionComponent.arrowsPerSecond) {
Vector3f target = event.getHitNormal();
Vector3i blockPos = new Vector3i(target);
Vector3f position = new Vector3f(event.getOrigin());
Vector3f dir = new Vector3f(event.getDirection());
HitResult result;
result = physicsRenderer.rayTrace(position, dir, arrowActionComponent.maxDistance, filter);
Block currentBlock = worldProvider.getBlock(blockPos);
if (currentBlock.isDestructible()) {
EntityBuilder builder = entityManager.newBuilder("Core:defaultBlockParticles");
builder.getComponent(LocationComponent.class).setWorldPosition(target);
builder.build();
}
EntityRef blockEntity = result.getEntity();
blockEntity.send(new DoDamageEvent(arrowActionComponent.damageAmount, arrowActionComponent.damageType));
lastTime = time.getGameTime();
}
}
use of org.terasology.physics.HitResult in project Terasology by MovingBlocks.
the class CharacterInventorySystem method onDropItemRequest.
@ReceiveEvent(components = { CharacterComponent.class, InventoryComponent.class }, netFilter = RegisterMode.CLIENT)
public void onDropItemRequest(DropItemButton event, EntityRef entity) {
CharacterHeldItemComponent characterHeldItemComponent = entity.getComponent(CharacterHeldItemComponent.class);
EntityRef selectedItemEntity = characterHeldItemComponent.selectedItem;
if (selectedItemEntity.equals(EntityRef.NULL)) {
return;
}
// this is a repeating event.
if (event.isDown() && lastTimeThrowInteraction == 0) {
lastTimeThrowInteraction = time.getGameTimeInMs();
return;
}
// resize the crosshair
InventoryHud toolbar = nuiManager.getHUD().getHUDElement("core:InventoryHud", InventoryHud.class);
if (toolbar != null) {
toolbar.setChargeAmount(getDropPower());
}
float dropPower = getDropPower();
// handle when we finally let go
if (!event.isDown()) {
// Compute new position
dropPower *= 150f;
Vector3f position = localPlayer.getViewPosition();
Vector3f direction = localPlayer.getViewDirection();
Vector3f maxAllowedDistanceInDirection = direction.mul(1.5f);
HitResult hitResult = physics.rayTrace(position, direction, 1.5f, StandardCollisionGroup.CHARACTER, StandardCollisionGroup.WORLD);
if (hitResult.isHit()) {
Vector3f possibleNewPosition = hitResult.getHitPoint();
maxAllowedDistanceInDirection = possibleNewPosition.sub(position);
}
Vector3f newPosition = position;
newPosition.add(maxAllowedDistanceInDirection.mul(0.9f));
// send DropItemRequest
Vector3f impulseVector = new Vector3f(direction);
impulseVector.scale(dropPower);
entity.send(new DropItemRequest(selectedItemEntity, entity, impulseVector, newPosition));
characterHeldItemComponent.lastItemUsedTime = time.getGameTimeInMs();
entity.saveComponent(characterHeldItemComponent);
resetDropMark();
}
event.consume();
}
Aggregations