mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-03-22 16:03:31 +00:00
the whole game
This commit is contained in:
513
src/client/player/LocalPlayer.cpp
Executable file
513
src/client/player/LocalPlayer.cpp
Executable file
@@ -0,0 +1,513 @@
|
||||
#include "LocalPlayer.h"
|
||||
#include "../Minecraft.h"
|
||||
#include "../../ErrorCodes.h"
|
||||
#include "../../world/entity/EntityEvent.h"
|
||||
#include "../../world/entity/player/Player.h"
|
||||
#include "../../world/inventory/BaseContainerMenu.h"
|
||||
#include "../../world/item/BowItem.h"
|
||||
#include "../../world/level/Level.h"
|
||||
#include "../../world/level/tile/Tile.h"
|
||||
#include "../../world/level/tile/entity/TileEntity.h"
|
||||
#include "../../world/level/material/Material.h"
|
||||
#include "../../network/packet/ContainerClosePacket.h"
|
||||
#include "../../network/packet/MovePlayerPacket.h"
|
||||
#include "../../network/packet/PlayerEquipmentPacket.h"
|
||||
#include "../../network/RakNetInstance.h"
|
||||
#include "../../network/packet/DropItemPacket.h"
|
||||
#include "../../network/packet/SetHealthPacket.h"
|
||||
#include "../../network/packet/SendInventoryPacket.h"
|
||||
#include "../../network/packet/EntityEventPacket.h"
|
||||
#include "../../network/packet/PlayerActionPacket.h"
|
||||
#ifndef STANDALONE_SERVER
|
||||
#include "../gui/Screen.h"
|
||||
#include "../gui/screens/FurnaceScreen.h"
|
||||
#include "../gui/screens/ChestScreen.h"
|
||||
#include "../gui/screens/crafting/WorkbenchScreen.h"
|
||||
#include "../gui/screens/crafting/StonecutterScreen.h"
|
||||
#include "../gui/screens/InBedScreen.h"
|
||||
#include "../gui/screens/TextEditScreen.h"
|
||||
#include "../particle/TakeAnimationParticle.h"
|
||||
#endif
|
||||
#include "../../network/packet/AnimatePacket.h"
|
||||
#include "../../world/item/ArmorItem.h"
|
||||
#include "../../network/packet/PlayerArmorEquipmentPacket.h"
|
||||
|
||||
//@note: doesn't work completely, since it doesn't care about stairs rotation
|
||||
static bool isJumpable(int tileId) {
|
||||
return tileId != Tile::fence->id
|
||||
&& tileId != Tile::fenceGate->id
|
||||
&& tileId != Tile::stoneSlabHalf->id
|
||||
&& tileId != Tile::trapdoor->id
|
||||
&& tileId != Tile::sign->id
|
||||
&& tileId != Tile::wallSign->id
|
||||
&& (Tile::tiles[tileId] != NULL && Tile::tiles[tileId]->getRenderShape() != Tile::SHAPE_STAIRS);
|
||||
}
|
||||
|
||||
LocalPlayer::LocalPlayer(Minecraft* minecraft, Level* level, User* user, int dimension, bool isCreative)
|
||||
: Player(level, isCreative),
|
||||
minecraft(minecraft),
|
||||
input(NULL),
|
||||
sentInventoryItemId(-1),
|
||||
sentInventoryItemData(-1),
|
||||
autoJumpEnabled(true),
|
||||
armorTypeHash(0)
|
||||
{
|
||||
this->dimension = dimension;
|
||||
_init();
|
||||
|
||||
if (user != NULL) {
|
||||
if (user->name.length() > 0)
|
||||
//customTextureUrl = "http://s3.amazonaws.com/MinecraftSkins/" + user.name + ".png";
|
||||
this->name = user->name;
|
||||
}
|
||||
}
|
||||
|
||||
LocalPlayer::~LocalPlayer() {
|
||||
//delete input;
|
||||
//input = NULL;
|
||||
}
|
||||
|
||||
/*private*/
|
||||
void LocalPlayer::calculateFlight(float xa, float ya, float za) {
|
||||
|
||||
xa = xa * minecraft->options.flySpeed;
|
||||
ya = 0;
|
||||
za = za * minecraft->options.flySpeed;
|
||||
|
||||
#ifdef ANDROID
|
||||
if (Keyboard::isKeyDown(103)) ya = .2f * minecraft->options.flySpeed;
|
||||
if (Keyboard::isKeyDown(102)) ya = -.2f * minecraft->options.flySpeed;
|
||||
#else
|
||||
if (Keyboard::isKeyDown(Keyboard::KEY_E)) ya = .2f * minecraft->options.flySpeed;
|
||||
if (Keyboard::isKeyDown(Keyboard::KEY_Q)) ya = -.2f * minecraft->options.flySpeed;
|
||||
#endif
|
||||
|
||||
flyX = 10 * smoothFlyX.getNewDeltaValue(xa, .35f * minecraft->options.sensitivity);
|
||||
flyY = 10 * smoothFlyY.getNewDeltaValue(ya, .35f * minecraft->options.sensitivity);
|
||||
flyZ = 10 * smoothFlyZ.getNewDeltaValue(za, .35f * minecraft->options.sensitivity);
|
||||
}
|
||||
|
||||
bool LocalPlayer::isSolidTile(int x, int y, int z) {
|
||||
int tileId = level->getTile(x, y, z);
|
||||
return tileId > 0 && Tile::tiles[tileId]->material->isSolid();
|
||||
}
|
||||
|
||||
void LocalPlayer::tick() {
|
||||
|
||||
super::tick();
|
||||
if(!useItem.isNull()) {
|
||||
ItemInstance* item = inventory->getSelected();
|
||||
if(item != NULL && *item == useItem) {
|
||||
if (useItemDuration <= 25 && useItemDuration % 4 == 0) {
|
||||
spawnEatParticles(item, 5);
|
||||
}
|
||||
if(--useItemDuration == 0) {
|
||||
if(!level->isClientSide) {
|
||||
completeUsingItem();
|
||||
} else {
|
||||
EntityEventPacket p(entityId, EntityEvent::USE_ITEM_COMPLETE);
|
||||
level->raknetInstance->send(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
stopUsingItem();
|
||||
}
|
||||
}
|
||||
if (minecraft->isOnline())
|
||||
{
|
||||
if (std::abs(x - sentX) > .1f || std::abs(y - sentY) > .01f || std::abs(z - sentZ) > .1f || std::abs(sentRotX - xRot) > 1 || std::abs(sentRotY - yRot) > 1)
|
||||
{
|
||||
MovePlayerPacket packet(entityId, x, y - heightOffset, z, xRot, yRot);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
sentX = x;
|
||||
sentY = y;
|
||||
sentZ = z;
|
||||
sentRotX = xRot;
|
||||
sentRotY = yRot;
|
||||
}
|
||||
|
||||
ItemInstance* item = inventory->getSelected();
|
||||
int newItemId = (item && item->count > 0) ? item->id : 0;
|
||||
int newItemData = (item && item->count > 0) ? item->getAuxValue() : 0;
|
||||
|
||||
if (sentInventoryItemId != newItemId
|
||||
|| sentInventoryItemData != newItemData)
|
||||
{
|
||||
sentInventoryItemId = newItemId;
|
||||
sentInventoryItemData = newItemData;
|
||||
PlayerEquipmentPacket packet(entityId, newItemId, newItemData);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
ItemInstance* a = getArmor(i);
|
||||
if (!a) continue;
|
||||
|
||||
ArmorItem* item = (ArmorItem*) a->getItem();
|
||||
|
||||
printf("armor %d: %d\n", i, a->getAuxValue());
|
||||
}
|
||||
/**/
|
||||
|
||||
updateArmorTypeHash();
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (!minecraft->screen && containerMenu) {
|
||||
static bool hasPostedError = false;
|
||||
if (!hasPostedError) {
|
||||
minecraft->gui.postError( ErrorCodes::ContainerRefStillExistsAfterDestruction );
|
||||
hasPostedError = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//LOGI("biome: %s\n", level->getBiomeSource()->getBiome((int)x >> 4, (int)z >> 4)->name.c_str());
|
||||
}
|
||||
|
||||
/*public*/
|
||||
void LocalPlayer::aiStep() {
|
||||
jumpTriggerTime--;
|
||||
ascendTriggerTime--;
|
||||
descendTriggerTime--;
|
||||
|
||||
bool wasJumping = input->jumping;
|
||||
#ifndef STANDALONE_SERVER
|
||||
bool screenCovering = minecraft->screen && !minecraft->screen->passEvents;
|
||||
if (!screenCovering)
|
||||
input->tick(this);
|
||||
|
||||
if (input->sneaking) {
|
||||
if (ySlideOffset < 0.2f) ySlideOffset = 0.2f;
|
||||
}
|
||||
#endif
|
||||
if (abilities.mayfly) {
|
||||
// Check for flight toggle
|
||||
if (!wasJumping && input->jumping) {
|
||||
if (jumpTriggerTime <= 0) jumpTriggerTime = 7;
|
||||
else {
|
||||
abilities.flying = !abilities.flying;
|
||||
jumpTriggerTime = 0;
|
||||
}
|
||||
}
|
||||
if (abilities.flying) {
|
||||
if (input->wantUp) {
|
||||
yd += 0.15f;
|
||||
//xd = zd = 0;
|
||||
}
|
||||
if (input->wantDown) {
|
||||
yd -= 0.15f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isUsingItem()) {
|
||||
const float k = 0.35f;
|
||||
input->xa *= k;
|
||||
input->ya *= k;
|
||||
}
|
||||
|
||||
Mob::aiStep();
|
||||
super::aiStep();
|
||||
|
||||
//if (onGround && abilities.flying)
|
||||
// abilities.flying = false;
|
||||
|
||||
if (interpolateOnly())
|
||||
updateAi();
|
||||
}
|
||||
|
||||
/*public*/
|
||||
void LocalPlayer::closeContainer() {
|
||||
if (level->isClientSide) {
|
||||
ContainerClosePacket packet(containerMenu->containerId);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
}
|
||||
super::closeContainer();
|
||||
minecraft->setScreen(NULL);
|
||||
}
|
||||
|
||||
//@Override
|
||||
void LocalPlayer::move(float xa, float ya, float za) {
|
||||
//@note: why is this == minecraft->player needed?
|
||||
if (this == minecraft->player && minecraft->options.isFlying) {
|
||||
noPhysics = true;
|
||||
float tmp = walkDist; // update
|
||||
calculateFlight((float) xa, (float) ya, (float) za);
|
||||
fallDistance = 0;
|
||||
yd = 0;
|
||||
super::move(flyX, flyY, flyZ);
|
||||
onGround = true;
|
||||
walkDist = tmp;
|
||||
} else {
|
||||
if (autoJumpTime > 0) {
|
||||
autoJumpTime--;
|
||||
input->jumping = true;
|
||||
}
|
||||
float prevX = x, prevZ = z;
|
||||
|
||||
super::move(xa, ya, za);
|
||||
|
||||
float newX = x, newZ = z;
|
||||
|
||||
if (autoJumpTime <= 0 && autoJumpEnabled)
|
||||
{
|
||||
// auto-jump when crossing the middle of a tile, and the tile in the front is blocked
|
||||
bool jump = false;
|
||||
if (Mth::floor(prevX * 2.0f) != Mth::floor(newX * 2.0f) || Mth::floor(prevZ * 2.0f) != Mth::floor(newZ * 2.0f))
|
||||
{
|
||||
float dist = Mth::sqrt(xa * xa + za * za);
|
||||
const int xx = Mth::floor(x + xa / dist);
|
||||
const int zz = Mth::floor(z + za / dist);
|
||||
const int tileId = level->getTile(xx, (int)(y-1), zz);
|
||||
jump = (isSolidTile(xx, (int)(y-1), zz) // Solid block to jump up on
|
||||
&& !isSolidTile(xx, (int)y, zz) && !isSolidTile(xx, (int)(y+1), zz)) // Enough space
|
||||
&& isJumpable(tileId);
|
||||
}
|
||||
if (jump)
|
||||
{
|
||||
autoJumpTime = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::updateAi() {
|
||||
super::updateAi();
|
||||
this->xxa = input->xa;
|
||||
this->yya = input->ya;
|
||||
this->jumping = input->jumping || autoJumpTime > 0;
|
||||
}
|
||||
|
||||
void LocalPlayer::take( Entity* e, int orgCount )
|
||||
{
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (e->isItemEntity())
|
||||
minecraft->particleEngine->add(new TakeAnimationParticle(minecraft->level, (ItemEntity*)e, this, -0.5f));
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayer::setKey( int eventKey, bool eventKeyState )
|
||||
{
|
||||
input->setKey(eventKey, eventKeyState);
|
||||
}
|
||||
|
||||
void LocalPlayer::releaseAllKeys()
|
||||
{
|
||||
if (input) input->releaseAllKeys();
|
||||
}
|
||||
|
||||
float LocalPlayer::getFieldOfViewModifier() {
|
||||
float targetFov = 1.0f;
|
||||
if(abilities.flying) targetFov *= 1.1f;
|
||||
targetFov *= ((walkingSpeed * getWalkingSpeedModifier()) / DEFAULT_WALK_SPEED +1) / 2;
|
||||
|
||||
if(isUsingItem() && getUseItem()->id == Item::bow->id) {
|
||||
float ticksHeld = (float)getTicksUsingItem();
|
||||
float scale = ticksHeld / BowItem::MAX_DRAW_DURATION;
|
||||
if(scale > 1) {
|
||||
scale = 1;
|
||||
}
|
||||
else {
|
||||
scale *= scale;
|
||||
}
|
||||
targetFov *= 1.0f - scale * 0.15f;
|
||||
}
|
||||
return targetFov;
|
||||
}
|
||||
void LocalPlayer::addAdditonalSaveData( CompoundTag* entityTag )
|
||||
{
|
||||
super::addAdditonalSaveData(entityTag);
|
||||
entityTag->putInt("Score", score);
|
||||
}
|
||||
|
||||
void LocalPlayer::readAdditionalSaveData( CompoundTag* entityTag )
|
||||
{
|
||||
super::readAdditionalSaveData(entityTag);
|
||||
score = entityTag->getInt("Score");
|
||||
}
|
||||
|
||||
bool LocalPlayer::isSneaking()
|
||||
{
|
||||
return input->sneaking;
|
||||
}
|
||||
|
||||
void LocalPlayer::hurtTo( int newHealth )
|
||||
{
|
||||
int dmg = health - newHealth;
|
||||
if (dmg <= 0) {
|
||||
this->health = newHealth;
|
||||
} else {
|
||||
lastHurt = dmg;
|
||||
lastHealth = health;
|
||||
invulnerableTime = invulnerableDuration;
|
||||
|
||||
minecraft->player->bypassArmor = true;
|
||||
actuallyHurt(dmg);
|
||||
minecraft->player->bypassArmor = false;
|
||||
|
||||
hurtTime = hurtDuration = 10;
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::actuallyHurt( int dmg )
|
||||
{
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (minecraft->screen && minecraft->screen->closeOnPlayerHurt()) {
|
||||
if (containerMenu) closeContainer();
|
||||
else minecraft->setScreen(NULL);
|
||||
}
|
||||
#endif
|
||||
super::actuallyHurt(dmg);
|
||||
}
|
||||
|
||||
void LocalPlayer::respawn()
|
||||
{
|
||||
minecraft->respawnPlayer();
|
||||
}
|
||||
|
||||
void LocalPlayer::die(Entity* source)
|
||||
{
|
||||
// If we're an online client, send the inventory to be dropped
|
||||
// If we're the server, drop the inventory immediately
|
||||
if (level->isClientSide) {
|
||||
SendInventoryPacket packet(this, true);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
}
|
||||
inventory->dropAll(level->isClientSide);
|
||||
for (int i = 0; i < NUM_ARMOR; ++i) {
|
||||
ItemInstance* item = getArmor(i);
|
||||
if (!ItemInstance::isArmorItem(item)) return;
|
||||
|
||||
drop(new ItemInstance(*item), true);
|
||||
setArmor(i, NULL);
|
||||
}
|
||||
|
||||
super::die(source);
|
||||
}
|
||||
|
||||
void LocalPlayer::swing() {
|
||||
super::swing();
|
||||
|
||||
if (swingTime == -1) {
|
||||
AnimatePacket packet(AnimatePacket::Swing, this);
|
||||
packet.reliability = UNRELIABLE;
|
||||
packet.priority = MEDIUM_PRIORITY;
|
||||
minecraft->raknetInstance->send(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::reset() {
|
||||
super::reset();
|
||||
this->_init();
|
||||
}
|
||||
|
||||
void LocalPlayer::_init() {
|
||||
autoJumpTime = 0;
|
||||
jumpTriggerTime = 0;
|
||||
ascendTriggerTime = 0;
|
||||
descendTriggerTime = 0;
|
||||
ascending = false;
|
||||
descending = false;
|
||||
|
||||
ItemInstance* item = inventory->getSelected();
|
||||
sentInventoryItemId = item? item->id : 0;
|
||||
sentInventoryItemData = item? item->getAuxValue() : 0;
|
||||
}
|
||||
|
||||
void LocalPlayer::startCrafting(int x, int y, int z, int tableSize) {
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (!minecraft->isCreativeMode())
|
||||
minecraft->setScreen( new WorkbenchScreen(tableSize) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayer::startStonecutting(int x, int y, int z) {
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (!minecraft->isCreativeMode())
|
||||
minecraft->setScreen( new StonecutterScreen() );
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayer::openFurnace( FurnaceTileEntity* e ) {
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (!minecraft->isCreativeMode())
|
||||
minecraft->setScreen( new FurnaceScreen(this, e) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayer::openContainer( ChestTileEntity* container ) {
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (!minecraft->isCreativeMode())
|
||||
minecraft->setScreen( new ChestScreen(this, container) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayer::drop( ItemInstance* item, bool randomly )
|
||||
{
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if (level->isClientSide) {
|
||||
DropItemPacket packet(entityId, *item);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
// delete the ItemEntity here, since we don't add it to level
|
||||
delete item;
|
||||
} else {
|
||||
super::drop(item, randomly);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::causeFallDamage( float distance )
|
||||
{
|
||||
int dmg = (int) ceil((distance - 3));
|
||||
if (dmg > 0) {
|
||||
if (level->isClientSide) {
|
||||
SetHealthPacket packet(SetHealthPacket::HEALTH_MODIFY_OFFSET + dmg);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
}
|
||||
}
|
||||
super::causeFallDamage(distance);
|
||||
|
||||
}
|
||||
|
||||
void LocalPlayer::displayClientMessage( const std::string& messageId ) {
|
||||
#ifndef STANDALONE_SERVER
|
||||
minecraft->gui.displayClientMessage(messageId);
|
||||
#endif
|
||||
}
|
||||
|
||||
int LocalPlayer::startSleepInBed( int x, int y, int z ) {
|
||||
int startSleepInBedReturnValue = super::startSleepInBed(x, y, z);
|
||||
#ifndef STANDALONE_SERVER
|
||||
if(startSleepInBedReturnValue == BedSleepingResult::OK)
|
||||
minecraft->setScreen(new InBedScreen());
|
||||
#endif
|
||||
return startSleepInBedReturnValue;
|
||||
}
|
||||
|
||||
void LocalPlayer::stopSleepInBed( bool forcefulWakeUp, bool updateLevelList, bool saveRespawnPoint ) {
|
||||
if(level->isClientSide) {
|
||||
PlayerActionPacket packet(PlayerActionPacket::STOP_SLEEPING, 0, 0, 0, 0, entityId);
|
||||
minecraft->raknetInstance->send(packet);
|
||||
}
|
||||
#ifndef STANDALONE_SERVER
|
||||
minecraft->setScreen(NULL);
|
||||
#endif
|
||||
super::stopSleepInBed(forcefulWakeUp, updateLevelList, saveRespawnPoint);
|
||||
}
|
||||
|
||||
void LocalPlayer::openTextEdit( TileEntity* tileEntity ) {
|
||||
#if !defined(STANDALONE_SERVER) && !defined(RPI)
|
||||
if(tileEntity->type == TileEntityType::Sign)
|
||||
minecraft->setScreen(new TextEditScreen((SignTileEntity*) tileEntity));
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayer::updateArmorTypeHash() {
|
||||
int hash = getArmorTypeHash();
|
||||
if (hash != armorTypeHash) {
|
||||
PlayerArmorEquipmentPacket p(this);
|
||||
minecraft->raknetInstance->send(p);
|
||||
armorTypeHash = hash;
|
||||
}
|
||||
}
|
||||
104
src/client/player/LocalPlayer.h
Executable file
104
src/client/player/LocalPlayer.h
Executable file
@@ -0,0 +1,104 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__LocalPlayer_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__LocalPlayer_H__
|
||||
|
||||
//package net.minecraft.client.player;
|
||||
|
||||
#include "input/IMoveInput.h"
|
||||
#include "../User.h"
|
||||
#include "../../platform/input/Keyboard.h"
|
||||
#include "../../util/SmoothFloat.h"
|
||||
#include "../../world/entity/player/Player.h"
|
||||
|
||||
class Minecraft;
|
||||
class Stat;
|
||||
class CompoundTag;
|
||||
|
||||
class LocalPlayer: public Player
|
||||
{
|
||||
typedef Player super;
|
||||
public:
|
||||
LocalPlayer(Minecraft* minecraft, Level* level, User* user, int dimension, bool isCreative);
|
||||
~LocalPlayer();
|
||||
|
||||
void _init();
|
||||
virtual void reset();
|
||||
|
||||
void tick();
|
||||
void move(float xa, float ya, float za);
|
||||
|
||||
void aiStep();
|
||||
void updateAi();
|
||||
|
||||
void setKey(int eventKey, bool eventKeyState);
|
||||
void releaseAllKeys();
|
||||
|
||||
void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
void readAdditionalSaveData(CompoundTag* entityTag);
|
||||
|
||||
void closeContainer();
|
||||
|
||||
void drop(ItemInstance* item, bool randomly);
|
||||
void take(Entity* e, int orgCount);
|
||||
|
||||
void startCrafting(int x, int y, int z, int tableSize);
|
||||
void startStonecutting(int x, int y, int z);
|
||||
|
||||
void openContainer(ChestTileEntity* container);
|
||||
void openFurnace(FurnaceTileEntity* e);
|
||||
|
||||
bool isSneaking();
|
||||
|
||||
void actuallyHurt(int dmg);
|
||||
void hurtTo(int newHealth);
|
||||
void die(Entity* source);
|
||||
|
||||
void respawn();
|
||||
|
||||
void animateRespawn() {}
|
||||
float getFieldOfViewModifier();
|
||||
void chat(const std::string& message) {}
|
||||
void displayClientMessage(const std::string& messageId);
|
||||
|
||||
void awardStat(Stat* stat, int count) {
|
||||
//minecraft->stats.award(stat, count);
|
||||
//minecraft->achievementPopup.popup("Achievement get!", stat.name);
|
||||
}
|
||||
void causeFallDamage( float distance );
|
||||
|
||||
virtual int startSleepInBed(int x, int y, int z);
|
||||
virtual void stopSleepInBed(bool forcefulWakeUp, bool updateLevelList, bool saveRespawnPoint);
|
||||
|
||||
void swing();
|
||||
virtual void openTextEdit( TileEntity* tileEntity );
|
||||
private:
|
||||
void calculateFlight(float xa, float ya, float za);
|
||||
bool isSolidTile(int x, int y, int z);
|
||||
void updateArmorTypeHash();
|
||||
public:
|
||||
IMoveInput* input;
|
||||
bool autoJumpEnabled;
|
||||
protected:
|
||||
Minecraft* minecraft;
|
||||
int jumpTriggerTime;
|
||||
int ascendTriggerTime;
|
||||
int descendTriggerTime;
|
||||
bool ascending, descending;
|
||||
private:
|
||||
// local player fly
|
||||
// -----------------------
|
||||
float flyX, flyY, flyZ;
|
||||
|
||||
// smooth camera settings
|
||||
SmoothFloat smoothFlyX;
|
||||
SmoothFloat smoothFlyY;
|
||||
SmoothFloat smoothFlyZ;
|
||||
|
||||
int autoJumpTime;
|
||||
|
||||
int sentInventoryItemId;
|
||||
int sentInventoryItemData;
|
||||
|
||||
int armorTypeHash;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__LocalPlayer_H__*/
|
||||
35
src/client/player/RemotePlayer.cpp
Executable file
35
src/client/player/RemotePlayer.cpp
Executable file
@@ -0,0 +1,35 @@
|
||||
#include "RemotePlayer.h"
|
||||
#include "../../world/entity/player/Inventory.h"
|
||||
#include "../../world/entity/SharedFlags.h"
|
||||
|
||||
RemotePlayer::RemotePlayer(Level* level, bool isCreative)
|
||||
: Player(level, isCreative),
|
||||
hasStartedUsingItem(false)
|
||||
{
|
||||
hasFakeInventory = true;
|
||||
}
|
||||
|
||||
void RemotePlayer::tick() {
|
||||
super::tick();
|
||||
|
||||
if (!hasStartedUsingItem && getSharedFlag(SharedFlagsInformation::FLAG_USINGITEM)) {
|
||||
hasStartedUsingItem = true;
|
||||
ItemInstance* instance = inventory->getItem(Inventory::MAX_SELECTION_SIZE);
|
||||
if (instance) {
|
||||
Item* item = Item::items[instance->id];
|
||||
if (item) {
|
||||
startUsingItem(*instance, item->getUseDuration(instance));
|
||||
//LOGI("Start using item! %s\n", instance->getDescriptionId().c_str());
|
||||
}
|
||||
}
|
||||
} else if (hasStartedUsingItem && !getSharedFlag(SharedFlagsInformation::FLAG_USINGITEM)) {
|
||||
// LOGI("Stop using item! %s\n", useItem.getDescriptionId().c_str());
|
||||
stopUsingItem();
|
||||
hasStartedUsingItem = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RemotePlayer::aiStep() {
|
||||
updateAttackAnim();
|
||||
super::aiStep();
|
||||
}
|
||||
21
src/client/player/RemotePlayer.h
Executable file
21
src/client/player/RemotePlayer.h
Executable file
@@ -0,0 +1,21 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__RemotePlayer_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__RemotePlayer_H__
|
||||
|
||||
//package net.minecraft.client.player;
|
||||
|
||||
#include "../../world/entity/player/Player.h"
|
||||
|
||||
class Level;
|
||||
|
||||
class RemotePlayer: public Player
|
||||
{
|
||||
typedef Player super;
|
||||
public:
|
||||
RemotePlayer(Level* level, bool isCreative);
|
||||
void aiStep();
|
||||
void tick();
|
||||
private:
|
||||
bool hasStartedUsingItem;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__RemotePlayer_H__*/
|
||||
69
src/client/player/input/ControllerTurnInput.h
Executable file
69
src/client/player/input/ControllerTurnInput.h
Executable file
@@ -0,0 +1,69 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT_ControllerTurnInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT_ControllerTurnInput_H__
|
||||
|
||||
#include "ITurnInput.h"
|
||||
#include "../../../platform/input/Controller.h"
|
||||
|
||||
/** A Controller Turn input */
|
||||
class ControllerTurnInput : public ITurnInput {
|
||||
public:
|
||||
static const int MODE_OFFSET = 1;
|
||||
static const int MODE_DELTA = 2;
|
||||
|
||||
ControllerTurnInput(int controllerId, int mode_)
|
||||
: cid(controllerId),
|
||||
mode(mode_),
|
||||
cxO(0), cyO(0),
|
||||
wasActive(false)
|
||||
{}
|
||||
|
||||
bool isTouched() { return Controller::isTouched(cid); }
|
||||
|
||||
TurnDelta getTurnDelta() {
|
||||
float dx = 0, dy = 0;
|
||||
bool isActive = Controller::isTouched(cid);
|
||||
|
||||
if (MODE_OFFSET == mode) {
|
||||
float dt = getDeltaTime();
|
||||
const float MaxTurnX = 250.0f;
|
||||
const float MaxTurnY = 200.0f;
|
||||
float cx = isActive? Controller::getX(cid) : cxO * 0.7f;
|
||||
float cy = isActive? Controller::getY(cid) : cyO * 0.7f;
|
||||
dx = linearTransform( cx, 0.1f, MaxTurnX ) * dt;
|
||||
dy = linearTransform( cy, 0.1f, MaxTurnY ) * dt;
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
} else
|
||||
if (MODE_DELTA == mode && (wasActive || isActive)) {
|
||||
float cx = Controller::getX(cid);
|
||||
float cy = Controller::getY(cid);
|
||||
|
||||
// const float dt = getDeltaTime();
|
||||
const float MaxTurnX = 100.0f;
|
||||
const float MaxTurnY = 100.0f;
|
||||
const float DeadZone = 0;//0.25f * dt;//0.02f;
|
||||
|
||||
if (!wasActive) {
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
}
|
||||
if (isActive) {
|
||||
dx = linearTransform(cx - cxO, DeadZone) * MaxTurnX;
|
||||
dy = linearTransform(cy - cyO, DeadZone) * MaxTurnY;
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
}
|
||||
}
|
||||
|
||||
wasActive = isActive;
|
||||
return TurnDelta(dx, -dy);
|
||||
}
|
||||
|
||||
int mode;
|
||||
private:
|
||||
int cid;
|
||||
float cxO, cyO;
|
||||
bool wasActive;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT_ControllerTurnInput_H__*/
|
||||
45
src/client/player/input/IBuildInput.h
Executable file
45
src/client/player/input/IBuildInput.h
Executable file
@@ -0,0 +1,45 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT__IBuildInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT__IBuildInput_H__
|
||||
|
||||
#include "../../IConfigListener.h"
|
||||
class Player;
|
||||
|
||||
class BuildActionIntention {
|
||||
public:
|
||||
BuildActionIntention()
|
||||
: action(0)
|
||||
{}
|
||||
BuildActionIntention(int action)
|
||||
: action(action)
|
||||
{}
|
||||
|
||||
bool isFirstRemove() { return (action & BAI_FIRSTREMOVE) != 0; }
|
||||
bool isRemoveContinue() { return (action & BAI_REMOVE) != 0; }
|
||||
|
||||
bool isBuild() { return (action & BAI_BUILD) != 0; }
|
||||
bool isRemove() { return isFirstRemove() || isRemoveContinue(); }
|
||||
|
||||
bool isAttack() { return (action & BAI_ATTACK) != 0; }
|
||||
bool isInteract() { return (action & BAI_INTERACT) != 0; }
|
||||
|
||||
int action;
|
||||
|
||||
static const int BAI_BUILD = 1;
|
||||
static const int BAI_REMOVE = 2;
|
||||
static const int BAI_FIRSTREMOVE = 4;
|
||||
|
||||
static const int BAI_ATTACK = 8;
|
||||
static const int BAI_INTERACT = 16;
|
||||
};
|
||||
|
||||
|
||||
class IBuildInput: public IConfigListener {
|
||||
public:
|
||||
virtual ~IBuildInput(){}
|
||||
|
||||
virtual void onConfigChanged(const Config& c) {}
|
||||
// @return true if user wants to do an action, false if not
|
||||
virtual bool tickBuild(Player*, BuildActionIntention* bai) { return false; }
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT__IBuildInput_H__*/
|
||||
75
src/client/player/input/IInputHolder.h
Executable file
75
src/client/player/input/IInputHolder.h
Executable file
@@ -0,0 +1,75 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__IInputHolder_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__IInputHolder_H__
|
||||
|
||||
#include "IMoveInput.h"
|
||||
#include "ITurnInput.h"
|
||||
#include "IBuildInput.h"
|
||||
|
||||
#include "../../../platform/input/Mouse.h"
|
||||
|
||||
class Player;
|
||||
|
||||
class IInputHolder: public IConfigListener
|
||||
{
|
||||
public:
|
||||
IInputHolder()
|
||||
: mousex(0),
|
||||
mousey(0),
|
||||
alpha(0)
|
||||
{}
|
||||
|
||||
virtual ~IInputHolder() {}
|
||||
|
||||
virtual void render(float alpha) {}
|
||||
|
||||
virtual bool allowPicking() {
|
||||
mousex = Mouse::getX();
|
||||
mousey = Mouse::getY();
|
||||
return Mouse::getButtonState(MouseAction::ACTION_LEFT) == MouseAction::DATA_DOWN;
|
||||
}
|
||||
|
||||
void onConfigChanged(const Config& c) {
|
||||
getMoveInput()->onConfigChanged(c);
|
||||
getTurnInput()->onConfigChanged(c);
|
||||
getBuildInput()->onConfigChanged(c);
|
||||
}
|
||||
|
||||
virtual IMoveInput* getMoveInput() = 0;
|
||||
virtual ITurnInput* getTurnInput() = 0;
|
||||
virtual IBuildInput* getBuildInput() = 0;
|
||||
|
||||
float mousex, mousey;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
|
||||
class CustomInputHolder: public IInputHolder
|
||||
{
|
||||
public:
|
||||
CustomInputHolder(IMoveInput* move, ITurnInput* turn, IBuildInput* build)
|
||||
{
|
||||
setInputs(move, turn, build);
|
||||
}
|
||||
|
||||
~CustomInputHolder() {
|
||||
delete _move;
|
||||
delete _turn;
|
||||
delete _build;
|
||||
}
|
||||
void setInputs(IMoveInput* move, ITurnInput* turn, IBuildInput* build) {
|
||||
_move = move;
|
||||
_turn = turn;
|
||||
_build = build;
|
||||
}
|
||||
|
||||
virtual IMoveInput* getMoveInput() { return _move; }
|
||||
virtual ITurnInput* getTurnInput() { return _turn; }
|
||||
virtual IBuildInput* getBuildInput() { return _build; }
|
||||
|
||||
private:
|
||||
IMoveInput* _move;
|
||||
ITurnInput* _turn;
|
||||
IBuildInput* _build;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__IInputHolder_H__*/
|
||||
47
src/client/player/input/IMoveInput.h
Executable file
47
src/client/player/input/IMoveInput.h
Executable file
@@ -0,0 +1,47 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__IMoveInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__IMoveInput_H__
|
||||
|
||||
//package net.minecraft.client.player;
|
||||
|
||||
#include "../../IConfigListener.h"
|
||||
class Player;
|
||||
class Minecraft;
|
||||
|
||||
class IMoveInput
|
||||
{
|
||||
protected:
|
||||
IMoveInput()
|
||||
: xa(0),
|
||||
ya(0),
|
||||
wasJumping(false),
|
||||
jumping(false),
|
||||
sneaking(false),
|
||||
wantUp(false),
|
||||
wantDown(false),
|
||||
isChangingFlightHeight(false)
|
||||
{}
|
||||
public:
|
||||
virtual ~IMoveInput() {}
|
||||
|
||||
virtual void tick(Player* player) {}
|
||||
virtual void render(float a) {}
|
||||
|
||||
virtual void setKey(int eventKey, bool eventKeyState) {}
|
||||
virtual void releaseAllKeys() {}
|
||||
|
||||
virtual void onConfigChanged(const Config& c) {}
|
||||
|
||||
public:
|
||||
float xa;
|
||||
float ya;
|
||||
|
||||
bool wasJumping;
|
||||
bool jumping;
|
||||
bool sneaking;
|
||||
|
||||
bool wantUp;
|
||||
bool wantDown;
|
||||
bool isChangingFlightHeight;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__IMoveInput_H__*/
|
||||
52
src/client/player/input/ITurnInput.h
Executable file
52
src/client/player/input/ITurnInput.h
Executable file
@@ -0,0 +1,52 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__ITurnInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__ITurnInput_H__
|
||||
|
||||
#include "../../../platform/time.h"
|
||||
#include "../../IConfigListener.h"
|
||||
#include <cmath>
|
||||
|
||||
/** Representing a Turn delta value */
|
||||
class TurnDelta {
|
||||
public:
|
||||
TurnDelta(float dx, float dy)
|
||||
: x(dx),
|
||||
y(dy)
|
||||
{}
|
||||
|
||||
float x, y;
|
||||
};
|
||||
|
||||
/** Base class for classes providing TurnDeltas */
|
||||
class ITurnInput: public IConfigListener {
|
||||
public:
|
||||
virtual ~ITurnInput() {}
|
||||
virtual void onConfigChanged(const Config& c) {}
|
||||
|
||||
virtual TurnDelta getTurnDelta() = 0;
|
||||
protected:
|
||||
ITurnInput()
|
||||
: _lastTime(-1.0f)
|
||||
{}
|
||||
|
||||
float getDeltaTime(){
|
||||
if (_lastTime == -1.0f) {
|
||||
_lastTime = getTimeS();
|
||||
}
|
||||
float now = getTimeS();
|
||||
float dt = now - _lastTime;
|
||||
_lastTime = now;
|
||||
return dt;
|
||||
}
|
||||
|
||||
static float linearTransform(float value, float deadZone, float scale=1.0f, bool limit1=false) {
|
||||
float deadSigned = value >= 0? deadZone : -deadZone;
|
||||
if (std::abs(deadSigned) >= std::abs(value)) return 0;
|
||||
float ret = (value - deadSigned) * scale;
|
||||
if (limit1 && std::abs(ret) > 1) ret /= std::abs(ret);
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
float _lastTime;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__ITurnInput_H__*/
|
||||
65
src/client/player/input/KeyboardInput.cpp
Executable file
65
src/client/player/input/KeyboardInput.cpp
Executable file
@@ -0,0 +1,65 @@
|
||||
#include "KeyboardInput.h"
|
||||
#include "../../Options.h"
|
||||
#include "../../../world/entity/player/Player.h"
|
||||
|
||||
KeyboardInput::KeyboardInput( Options* options )
|
||||
{
|
||||
for (int i = 0; i < NumKeys; ++i)
|
||||
keys[i] = false;
|
||||
this->options = options;
|
||||
}
|
||||
|
||||
void KeyboardInput::setKey( int key, bool state )
|
||||
{
|
||||
int id = -1;
|
||||
if (key == options->keyUp.key) id = KEY_UP;
|
||||
if (key == options->keyDown.key) id = KEY_DOWN;
|
||||
if (key == options->keyLeft.key) id = KEY_LEFT;
|
||||
if (key == options->keyRight.key) id = KEY_RIGHT;
|
||||
if (key == options->keyJump.key) id = KEY_JUMP;
|
||||
if (key == options->keySneak.key) id = KEY_SNEAK;
|
||||
if (key == options->keyCraft.key) id = KEY_CRAFT;
|
||||
//printf("key: %d\n", id);
|
||||
if (id >= 0) {
|
||||
keys[id] = state;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardInput::releaseAllKeys()
|
||||
{
|
||||
xa = 0;
|
||||
ya = 0;
|
||||
|
||||
for (int i = 0; i < NumKeys; i++) {
|
||||
keys[i] = false;
|
||||
}
|
||||
wantUp = wantDown = false;
|
||||
}
|
||||
|
||||
void KeyboardInput::tick( Player* player )
|
||||
{
|
||||
xa = 0;
|
||||
ya = 0;
|
||||
|
||||
if (keys[KEY_UP]) ya++;
|
||||
if (keys[KEY_DOWN]) ya--;
|
||||
if (keys[KEY_LEFT]) xa++;
|
||||
if (keys[KEY_RIGHT]) xa--;
|
||||
jumping = keys[KEY_JUMP];
|
||||
sneaking = keys[KEY_SNEAK];
|
||||
if (sneaking) {
|
||||
xa *= 0.3f;
|
||||
ya *= 0.3f;
|
||||
}
|
||||
|
||||
#if defined(RPI) || defined(PLATFORM_GLFW)
|
||||
wantUp = jumping;
|
||||
wantDown = sneaking;
|
||||
#endif
|
||||
|
||||
if (keys[KEY_CRAFT])
|
||||
player->startCrafting((int)player->x, (int)player->y, (int)player->z, Recipe::SIZE_2X2);
|
||||
|
||||
//printf("\n>- %f %f\n", xa, ya);
|
||||
}
|
||||
|
||||
36
src/client/player/input/KeyboardInput.h
Executable file
36
src/client/player/input/KeyboardInput.h
Executable file
@@ -0,0 +1,36 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__KeyboardInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__KeyboardInput_H__
|
||||
|
||||
//package net.minecraft.client.player;
|
||||
|
||||
#include "IMoveInput.h"
|
||||
|
||||
class Options;
|
||||
class Player;
|
||||
|
||||
// @todo: extract a separate MoveInput (-> merge XperiaPlayInput)
|
||||
class KeyboardInput: public IMoveInput
|
||||
{
|
||||
static const int NumKeys = 10;
|
||||
public:
|
||||
static const int KEY_UP = 0;
|
||||
static const int KEY_DOWN = 1;
|
||||
static const int KEY_LEFT = 2;
|
||||
static const int KEY_RIGHT = 3;
|
||||
static const int KEY_JUMP = 4;
|
||||
static const int KEY_SNEAK = 5;
|
||||
static const int KEY_CRAFT = 6;
|
||||
|
||||
KeyboardInput(Options* options);
|
||||
|
||||
void tick(Player* player);
|
||||
|
||||
void setKey(int key, bool state);
|
||||
void releaseAllKeys();
|
||||
|
||||
protected:
|
||||
bool keys[NumKeys];
|
||||
Options* options;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__KeyboardInput_H__*/
|
||||
36
src/client/player/input/MouseBuildInput.h
Executable file
36
src/client/player/input/MouseBuildInput.h
Executable file
@@ -0,0 +1,36 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT_MouseBuildInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT_MouseBuildInput_H__
|
||||
|
||||
#include "IBuildInput.h"
|
||||
#include "../../../platform/input/Mouse.h"
|
||||
|
||||
/** A Mouse Build input */
|
||||
class MouseBuildInput : public IBuildInput {
|
||||
public:
|
||||
MouseBuildInput()
|
||||
: buildDelayTicks(10),
|
||||
buildHoldTicks(0)
|
||||
{}
|
||||
|
||||
virtual bool tickBuild(Player* p, BuildActionIntention* bai) {
|
||||
if (Mouse::getButtonState(MouseAction::ACTION_LEFT) != 0) {
|
||||
*bai = BuildActionIntention(BuildActionIntention::BAI_REMOVE | BuildActionIntention::BAI_ATTACK);
|
||||
return true;
|
||||
}
|
||||
if (Mouse::getButtonState(MouseAction::ACTION_RIGHT) != 0) {
|
||||
if (buildHoldTicks >= buildDelayTicks) buildHoldTicks = 0;
|
||||
if (++buildHoldTicks == 1) {
|
||||
*bai = BuildActionIntention(BuildActionIntention::BAI_BUILD | BuildActionIntention::BAI_INTERACT);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
buildHoldTicks = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
int buildHoldTicks;
|
||||
int buildDelayTicks;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT_MouseBuildInput_H__*/
|
||||
43
src/client/player/input/MouseTurnInput.h
Executable file
43
src/client/player/input/MouseTurnInput.h
Executable file
@@ -0,0 +1,43 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT_MouseTurnInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT_MouseTurnInput_H__
|
||||
|
||||
#include "ITurnInput.h"
|
||||
#include "../../../platform/input/Mouse.h"
|
||||
|
||||
/** A Mouse Turn input */
|
||||
class MouseTurnInput : public ITurnInput {
|
||||
public:
|
||||
static const int MODE_OFFSET = 1;
|
||||
static const int MODE_DELTA = 2;
|
||||
|
||||
MouseTurnInput(int mode_, int centerX, int centerY)
|
||||
: mode(mode_),
|
||||
_centerX((float)centerX),
|
||||
_centerY((float)centerY)
|
||||
{}
|
||||
|
||||
void onConfigChanged(const Config& config) {
|
||||
_centerX = ((float) config.width ) * 0.5f;
|
||||
_centerY = ((float) config.height) * 0.5f;
|
||||
}
|
||||
|
||||
TurnDelta getTurnDelta() {
|
||||
float dx = 0, dy = 0;
|
||||
if ( MODE_DELTA == mode ) {
|
||||
dx = (float)Mouse::getDX();
|
||||
dy = (float)Mouse::getDY();
|
||||
} else if (MODE_OFFSET == mode) {
|
||||
float dt = getDeltaTime();
|
||||
dx = linearTransform( (float)Mouse::getX() - _centerX, 40, 0.4f ) * dt;
|
||||
dy = linearTransform( (float)Mouse::getY() - _centerY, 30, 0.6f ) * dt;
|
||||
}
|
||||
return TurnDelta(dx, dy);
|
||||
}
|
||||
|
||||
int mode;
|
||||
private:
|
||||
float _centerX;
|
||||
float _centerY;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT_MouseTurnInput_H__*/
|
||||
49
src/client/player/input/XperiaPlayInput.h
Executable file
49
src/client/player/input/XperiaPlayInput.h
Executable file
@@ -0,0 +1,49 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__XperiaPlayInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__XperiaPlayInput_H__
|
||||
|
||||
//package net.minecraft.client.player;
|
||||
|
||||
#include "KeyboardInput.h"
|
||||
|
||||
// @note: This is just copy-pasted from KeyboardInput right now.
|
||||
class XperiaPlayInput: public KeyboardInput
|
||||
{
|
||||
typedef KeyboardInput super;
|
||||
public:
|
||||
XperiaPlayInput(Options* options)
|
||||
: super(options),
|
||||
wasSneakTouched(false)
|
||||
{}
|
||||
|
||||
void tick(Player* player) {
|
||||
bool _sneaking = sneaking;
|
||||
super::tick(player);
|
||||
sneaking = _sneaking;
|
||||
|
||||
wantUp = (jumping && keys[KEY_UP]);
|
||||
wantDown = (jumping && keys[KEY_DOWN]);
|
||||
if ((wantUp | wantDown) && (player && player->abilities.flying)) ya = 0;
|
||||
|
||||
bool isSneakTouched = Controller::isTouched(1);
|
||||
if (isSneakTouched && !wasSneakTouched) {
|
||||
sneaking = !sneaking;
|
||||
}
|
||||
wasSneakTouched = isSneakTouched;
|
||||
|
||||
if (sneaking) {
|
||||
xa *= 0.3f;
|
||||
ya *= 0.3f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (Controller::isTouched(moveStick)) {
|
||||
xa = -Controller::getTransformedX(moveStick, 0.1f, 1.25f, true);
|
||||
ya = +Controller::getTransformedY(moveStick, 0.1f, 1.25f, true);
|
||||
}
|
||||
*/
|
||||
private:
|
||||
bool wasSneakTouched;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__XperiaPlayInput_H__*/
|
||||
14
src/client/player/input/touchscreen/ITouchScreenModel.h
Executable file
14
src/client/player/input/touchscreen/ITouchScreenModel.h
Executable file
@@ -0,0 +1,14 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__ITouchScreenModel_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__ITouchScreenModel_H__
|
||||
|
||||
#include "../../../../platform/input/Mouse.h"
|
||||
|
||||
class ITouchScreenModel
|
||||
{
|
||||
public:
|
||||
virtual ~ITouchScreenModel() {}
|
||||
virtual int getPointerId(const MouseAction& m) { return m.pointerId; }
|
||||
virtual int getPointerId(int x, int y, int pid) { return pid; }
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__ITouchScreenModel_H__*/
|
||||
339
src/client/player/input/touchscreen/TouchAreaModel.h
Executable file
339
src/client/player/input/touchscreen/TouchAreaModel.h
Executable file
@@ -0,0 +1,339 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER__TouchAreaModel_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER__TouchAreaModel_H__
|
||||
|
||||
#include "ITouchScreenModel.h"
|
||||
#include <vector>
|
||||
#include "../../../../platform/time.h"
|
||||
|
||||
/// Interface for an area that can be point tested
|
||||
class IArea{
|
||||
public:
|
||||
IArea()
|
||||
: deleteMe(true)
|
||||
{}
|
||||
|
||||
virtual ~IArea() {};
|
||||
virtual bool isInside(float x, float y) = 0;
|
||||
//virtual void expandRectToInclude(float& l, float& t, float& r, float& b) {}
|
||||
|
||||
bool deleteMe;
|
||||
};
|
||||
|
||||
/// Holder for multiple <IArea, int areaId> pairs
|
||||
class TouchAreaModel: public ITouchScreenModel
|
||||
{
|
||||
public:
|
||||
TouchAreaModel() {}
|
||||
|
||||
~TouchAreaModel() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (unsigned int i = 0; i < _areas.size(); ++i) {
|
||||
Area* a = _areas[i];
|
||||
if (a->area && a->area->deleteMe)
|
||||
delete a->area;
|
||||
delete a;
|
||||
}
|
||||
_areas.clear();
|
||||
}
|
||||
|
||||
int getPointerId(const MouseAction& m) {
|
||||
return getPointerId(m.x, m.y, m.pointerId);
|
||||
}
|
||||
|
||||
int getPointerId(int x, int y, int pid) {
|
||||
//static Stopwatch w;
|
||||
//w.printEvery(200, "IArea");
|
||||
//w.start();
|
||||
float fx = (float)x, fy = (float) y;
|
||||
for (unsigned int i = 0; i < _areas.size(); ++i) {
|
||||
const Area* a = _areas[i];
|
||||
if (a->area->isInside(fx, fy)) {
|
||||
//w.stop();
|
||||
return a->areaId;
|
||||
}
|
||||
}
|
||||
//w.stop();
|
||||
return pid;
|
||||
}
|
||||
|
||||
void addArea(int areaId, IArea* area) {
|
||||
Area* a = new Area();
|
||||
a->area = area;
|
||||
a->areaId = areaId;
|
||||
|
||||
_areas.push_back( a );
|
||||
}
|
||||
|
||||
private:
|
||||
struct Area {
|
||||
IArea* area;
|
||||
int areaId;
|
||||
};
|
||||
|
||||
std::vector<Area*> _areas;
|
||||
};
|
||||
|
||||
/// Area represented by a polygon
|
||||
class PolygonArea: public IArea
|
||||
{
|
||||
public:
|
||||
PolygonArea(int numPoints, const float* xp, const float* yp)
|
||||
: _numPoints(numPoints)
|
||||
{
|
||||
_x = new float[numPoints];
|
||||
_y = new float[numPoints];
|
||||
|
||||
for (int i = 0; i < numPoints; ++i) {
|
||||
_x[i] = xp[i];
|
||||
_y[i] = yp[i];
|
||||
}
|
||||
}
|
||||
|
||||
~PolygonArea() {
|
||||
delete[] _x;
|
||||
delete[] _y;
|
||||
}
|
||||
|
||||
virtual bool isInside(float x, float y)
|
||||
{
|
||||
bool c = false;
|
||||
for (int i = 0, j = _numPoints-1; i < _numPoints; j = i++) {
|
||||
if ((((_y[i] <= y) && (y < _y[j])) ||
|
||||
((_y[j] <= y) && (y < _y[i]))) &&
|
||||
(x < (_x[j] - _x[i]) * (y - _y[i]) / (_y[j] - _y[i]) + _x[i]))
|
||||
c = !c;
|
||||
}
|
||||
return c == 1;
|
||||
}
|
||||
|
||||
//private:
|
||||
float* _x;
|
||||
float* _y;
|
||||
int _numPoints;
|
||||
};
|
||||
|
||||
/// Area represented by a rectangle
|
||||
class RectangleArea: public IArea
|
||||
{
|
||||
public:
|
||||
RectangleArea(float x0, float y0, float x1, float y1)
|
||||
: _x0(x0),
|
||||
_x1(x1),
|
||||
_y0(y0),
|
||||
_y1(y1)
|
||||
{}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
return x >= _x0 && x <= _x1
|
||||
&& y >= _y0 && y <= _y1;
|
||||
}
|
||||
|
||||
virtual float centerX()
|
||||
{
|
||||
return _x0 + (_x1 - _x0) * .5f;
|
||||
}
|
||||
|
||||
virtual float centerY()
|
||||
{
|
||||
return _y0 + (_y1 - _y0) * .5f;
|
||||
}
|
||||
|
||||
//private:
|
||||
float _x0, _x1;
|
||||
float _y0, _y1;
|
||||
};
|
||||
|
||||
/// An area represented by a circle
|
||||
class CircleArea: public IArea
|
||||
{
|
||||
public:
|
||||
CircleArea(float x, float y, float r)
|
||||
: _x(x), _y(y), _rr(r*r)
|
||||
{}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
const float dx = x - _x;
|
||||
const float dy = y - _y;
|
||||
return (dx*dx + dy*dy) <= _rr;
|
||||
}
|
||||
|
||||
private:
|
||||
float _x, _y;
|
||||
float _rr;
|
||||
};
|
||||
|
||||
/// Inside any area in include list but none of exclude list
|
||||
class IncludeExcludeArea: public IArea
|
||||
{
|
||||
public:
|
||||
IncludeExcludeArea() {}
|
||||
|
||||
~IncludeExcludeArea() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (deleteMe) {
|
||||
for (unsigned int i = 0; i < _includes.size(); ++i) {
|
||||
IArea* area = _includes[i];
|
||||
if (area->deleteMe) delete area;
|
||||
}
|
||||
for (unsigned int i = 0; i < _excludes.size(); ++i) {
|
||||
IArea* area = _excludes[i];
|
||||
if (area->deleteMe) delete area;
|
||||
}
|
||||
}
|
||||
_includes.clear();
|
||||
_excludes.clear();
|
||||
}
|
||||
|
||||
void include(IArea* area) { _includes.push_back(area); }
|
||||
void exclude(IArea* area) { _excludes.push_back(area); }
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
for (unsigned int i = 0; i < _includes.size(); ++i)
|
||||
if (_includes[i]->isInside(x, y)) {
|
||||
bool good = true;
|
||||
//@todo: cache _exclude-test results
|
||||
for (unsigned int j = 0; j < _excludes.size(); ++j)
|
||||
if (_excludes[j]->isInside(x, y)) {
|
||||
good = false;
|
||||
break;
|
||||
}
|
||||
if (good) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<IArea*> _includes;
|
||||
std::vector<IArea*> _excludes;
|
||||
};
|
||||
|
||||
|
||||
/// At least one of the areas
|
||||
class OrArea: public IArea
|
||||
{
|
||||
public:
|
||||
OrArea(IArea* a, IArea* b)
|
||||
: _a(a),
|
||||
_b(b)
|
||||
{}
|
||||
|
||||
~OrArea() {
|
||||
if (deleteMe) {
|
||||
if (_a->deleteMe) delete _a;
|
||||
if (_b->deleteMe) delete _b;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
return _a->isInside(x, y) || _b->isInside(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
IArea* _a;
|
||||
IArea* _b;
|
||||
};
|
||||
|
||||
/// In both areas
|
||||
class AndArea: public IArea
|
||||
{
|
||||
public:
|
||||
AndArea(IArea* a, IArea* b)
|
||||
: _a(a),
|
||||
_b(b)
|
||||
{}
|
||||
|
||||
~AndArea() {
|
||||
if (deleteMe) {
|
||||
if (_a->deleteMe) delete _a;
|
||||
if (_b->deleteMe) delete _b;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
return _a->isInside(x, y) && _b->isInside(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
IArea* _a;
|
||||
IArea* _b;
|
||||
};
|
||||
|
||||
/// Exactly one of the areas
|
||||
class XorArea: public IArea
|
||||
{
|
||||
public:
|
||||
XorArea(IArea* a, IArea* b)
|
||||
: _a(a),
|
||||
_b(b)
|
||||
{}
|
||||
|
||||
~XorArea() {
|
||||
if (deleteMe) {
|
||||
if (_a->deleteMe) delete _a;
|
||||
if (_b->deleteMe) delete _b;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
return _a->isInside(x, y) ^ _b->isInside(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
IArea* _a;
|
||||
IArea* _b;
|
||||
};
|
||||
|
||||
/// Everything except this area
|
||||
class NotArea: public IArea
|
||||
{
|
||||
public:
|
||||
NotArea(IArea* a)
|
||||
: _a(a)
|
||||
{}
|
||||
|
||||
~NotArea() {
|
||||
if (deleteMe && _a->deleteMe) delete _a;
|
||||
}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
return !_a->isInside(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
IArea* _a;
|
||||
};
|
||||
|
||||
/// First area, but not second
|
||||
/// This is semantically the same as AndArea( a, new NotArea(b) )
|
||||
class DifferenceArea: public IArea
|
||||
{
|
||||
public:
|
||||
DifferenceArea(IArea* a, IArea* b)
|
||||
: _a(a),
|
||||
_b(b)
|
||||
{}
|
||||
|
||||
~DifferenceArea() {
|
||||
if (deleteMe) {
|
||||
if (_a->deleteMe) delete _a;
|
||||
if (_b->deleteMe) delete _b;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isInside(float x, float y) {
|
||||
return _a->isInside(x, y) && !_b->isInside(x, y);
|
||||
}
|
||||
private:
|
||||
IArea* _a;
|
||||
IArea* _b;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__TouchAreaModel_H__*/
|
||||
473
src/client/player/input/touchscreen/TouchInputHolder.h
Executable file
473
src/client/player/input/touchscreen/TouchInputHolder.h
Executable file
@@ -0,0 +1,473 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchInputHolder_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchInputHolder_H__
|
||||
|
||||
#include "../IInputHolder.h"
|
||||
#include "TouchscreenInput.h"
|
||||
|
||||
#include "../ITurnInput.h"
|
||||
#include "TouchAreaModel.h"
|
||||
#include "../../../../platform/input/Multitouch.h"
|
||||
#include "../../../../platform/time.h"
|
||||
#include "../../../../util/SmoothFloat.h"
|
||||
|
||||
#include "../../../../world/entity/player/Player.h"
|
||||
#include "../../../../world/entity/player/Inventory.h"
|
||||
|
||||
template <class T>
|
||||
class ModifyNotify {
|
||||
public:
|
||||
ModifyNotify()
|
||||
: _changed(false)
|
||||
{}
|
||||
|
||||
T& getOld() { return _old; }
|
||||
T& getNew() { return _new; }
|
||||
|
||||
bool update(T& val) {
|
||||
_changed = !equals(val);
|
||||
if (_changed) {
|
||||
_old = _new;
|
||||
_new = val;
|
||||
}
|
||||
return _changed;
|
||||
}
|
||||
|
||||
bool hasChanged() const { return _changed; }
|
||||
|
||||
virtual bool equals(const T& newVal) {
|
||||
return _old != newVal;
|
||||
}
|
||||
protected:
|
||||
T _old;
|
||||
private:
|
||||
T _new;
|
||||
bool _changed;
|
||||
};
|
||||
|
||||
//
|
||||
// Implementation for unified [Turn & Build Input]
|
||||
//
|
||||
class UnifiedTurnBuild: public GuiComponent,
|
||||
public ITurnInput,
|
||||
public IBuildInput
|
||||
{
|
||||
public:
|
||||
static const int MODE_OFFSET = 1;
|
||||
static const int MODE_DELTA = 2;
|
||||
|
||||
UnifiedTurnBuild(int turnMode, int width, int height, float maxMovementDelta, float sensitivity, IInputHolder* holder, Minecraft* minecraft)
|
||||
: mode(turnMode),
|
||||
_holder(holder),
|
||||
_options(&minecraft->options),
|
||||
cxO(0), cyO(0),
|
||||
wasActive(false),
|
||||
_totalMoveDelta(0),
|
||||
_maxMovement(maxMovementDelta),
|
||||
_lastPlayer(0),
|
||||
screenArea(-1, -1, 0, 0),
|
||||
allowPicking(false),
|
||||
state(State_None),
|
||||
moveArea(-1,-1,0,0),
|
||||
joyTouchArea(-1, -1, 0, 0),
|
||||
inventoryArea(-1,-1, 0, 0),
|
||||
pauseArea(-1, -1, 0, 0),
|
||||
_buildMovement(0),
|
||||
_sentFirstRemove(false),
|
||||
_canDestroy(false),
|
||||
_forceCanUse(false)
|
||||
{
|
||||
_area.deleteMe = false;
|
||||
setSensitivity(sensitivity);
|
||||
//((ITurnInput*)this)->onConfigChanged(createConfig(minecraft));
|
||||
onConfigChanged(createConfig(minecraft));
|
||||
|
||||
_lastBuildDownTime = _startTurnTime = getTimeS();
|
||||
}
|
||||
|
||||
void setSensitivity(float sensitivity) {
|
||||
_sensitivity = sensitivity;
|
||||
}
|
||||
|
||||
virtual void onConfigChanged(const Config& c) {
|
||||
if (false && _options->isJoyTouchArea) {
|
||||
int touchWidth = c.width - (int)inventoryArea._x1;
|
||||
if (touchWidth > (int)c.minecraft->pixelCalc.millimetersToPixels(60))
|
||||
touchWidth = (int)c.minecraft->pixelCalc.millimetersToPixels(60);
|
||||
|
||||
int touchHeight = (int)(c.height * 0.4f);
|
||||
if (touchHeight > (int)c.minecraft->pixelCalc.millimetersToPixels(40))
|
||||
touchHeight = (int)c.minecraft->pixelCalc.millimetersToPixels(40);
|
||||
|
||||
joyTouchArea._x0 = (float)(c.width - touchWidth);
|
||||
joyTouchArea._y0 = (float)(c.height - touchHeight);
|
||||
joyTouchArea._x1 = (float)c.width;
|
||||
joyTouchArea._y1 = (float)c.height;
|
||||
|
||||
_area.clear();
|
||||
_area.include (&joyTouchArea);
|
||||
_model.clear();
|
||||
_model.addArea(AREA_TURN, &_area);
|
||||
} else {
|
||||
screenArea = RectangleArea(0, 0, (float)c.width, (float)c.height);
|
||||
// Expand the move area a bit
|
||||
const float border = 10;
|
||||
const float widen = (moveArea._x1-moveArea._x0) * 0.05f + border; // ~5% wider
|
||||
moveArea._x0 -= widen;
|
||||
moveArea._x1 += widen;
|
||||
const float heighten = (moveArea._y1-moveArea._y0) * 0.05f + border; // ~5% taller
|
||||
moveArea._y0 -= heighten;
|
||||
moveArea._y1 += heighten;
|
||||
|
||||
pauseArea._x0 -= border;
|
||||
pauseArea._x1 += border;
|
||||
pauseArea._y0 -= border;
|
||||
pauseArea._y1 += border;
|
||||
|
||||
//LOGI("move: %f, %f, %f, %f\n", moveArea._x0, moveArea._y0, moveArea._x1, moveArea._y1);
|
||||
|
||||
_area.clear();
|
||||
_area.include(&screenArea);
|
||||
_area.exclude(&moveArea);
|
||||
_area.exclude(&inventoryArea);
|
||||
#ifdef __APPLE__
|
||||
_area.exclude(&pauseArea);
|
||||
#endif /*__APPLE__*/
|
||||
//LOGI("Movearea: %f %f %f% f\n", moveArea._x0, moveArea._x1, moveArea._y0, moveArea._y1);
|
||||
|
||||
_model.clear();
|
||||
_model.addArea(AREA_TURN, &_area);
|
||||
}
|
||||
}
|
||||
|
||||
float calcNewAlpha(float current, float wanted) {
|
||||
if (wanted > current)
|
||||
return Mth::clamp(current + 0.02f, 0.0f, wanted);
|
||||
if (wanted < current)
|
||||
return Mth::clamp(current - 0.04f, wanted, 1.0f);
|
||||
return current;
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation for the ITurnInput part
|
||||
//
|
||||
TurnDelta getTurnDelta() {
|
||||
float dx = 0, dy = 0;
|
||||
const float now = getTimeS();
|
||||
|
||||
float cx = 0;
|
||||
float cy = 0;
|
||||
bool isActive = false;
|
||||
|
||||
const int* pointerIds;
|
||||
bool wasFirstMovement = false;
|
||||
int pointerCount = Multitouch::getActivePointerIds(&pointerIds);
|
||||
for (int i = 0; i < pointerCount; ++i) {
|
||||
int p = pointerIds[i];
|
||||
int x = Multitouch::getX(p);
|
||||
int y = Multitouch::getY(p);
|
||||
int areaId = _model.getPointerId(x, y, p);
|
||||
|
||||
if (areaId == AREA_TURN) {
|
||||
isActive = true;
|
||||
cx = (float)x * 0.5f;
|
||||
cy = (float)y * -0.5f;
|
||||
wasFirstMovement = Multitouch::wasFirstMovement(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isActive && !wasActive) {
|
||||
_startTurnTime = now;
|
||||
_totalMoveDelta = 0;
|
||||
bool isInMovement = _lastPlayer? getSpeedSquared(_lastPlayer) > 0.01f/*.25f*/ : false;
|
||||
//state = isInMovement? State_Turn : State_Deciding;
|
||||
state = State_Deciding;
|
||||
_canDestroy = !isInMovement;
|
||||
_forceCanUse = false;
|
||||
if (!_canDestroy && (_lastPlayer && _lastPlayer->canUseCarriedItemWhileMoving())) {
|
||||
_forceCanUse = true;
|
||||
_canDestroy = true;
|
||||
}
|
||||
_sentFirstRemove = false;
|
||||
} else if (wasActive && !isActive) {
|
||||
_sentFirstRemove = false;
|
||||
state = State_None;
|
||||
//_inBuild = false;
|
||||
}
|
||||
|
||||
if (MODE_DELTA == mode && (wasActive || isActive)) {
|
||||
// const float dt = getDeltaTime();
|
||||
// const float MaxTurnX = 100.0f;
|
||||
// const float MaxTurnY = 100.0f;
|
||||
const float DeadZone = 0;//0.25f * dt;//0.02f;
|
||||
|
||||
if (!wasActive) {
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
}
|
||||
if (isActive) {
|
||||
dx = _sensitivity * linearTransform(cx - cxO, DeadZone);// * MaxTurnX;
|
||||
dy = _sensitivity * linearTransform(cy - cyO, DeadZone);// * MaxTurnY;
|
||||
|
||||
float moveDelta = ( Mth::abs(dx) + Mth::abs(dy) );
|
||||
//LOGI("moveDelta is : %f\n", moveDelta);
|
||||
|
||||
if (moveDelta > _maxMovement) {
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
moveDelta = 0;
|
||||
}
|
||||
_totalMoveDelta += moveDelta;
|
||||
|
||||
if (state == State_Deciding && _totalMoveDelta >= MaxBuildMovement/* && !_forceCanUse*/)
|
||||
state = State_Turn;
|
||||
|
||||
// If a certain time has passed since we pressed button; check if
|
||||
// we've moved enough to prevent removal state to become activated
|
||||
const float since = now - _startTurnTime;
|
||||
if (state == State_Deciding && (since >= (0.001f*RemovalMilliseconds))) {
|
||||
//LOGI("DECIDED!: %f\n", _totalMoveDelta);
|
||||
bool isInMovement = _lastPlayer? getSpeedSquared(_lastPlayer) > 0.01f/*.25f*/ : false;
|
||||
if (!_forceCanUse && (_totalMoveDelta > 20.0f || isInMovement)) {
|
||||
state = State_Turn;
|
||||
} else {
|
||||
state = State_Destroy;
|
||||
_canDestroy = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Removing the pointer ketchup-effect that's built into some devices
|
||||
if (wasFirstMovement) {
|
||||
dx = dy = 0;
|
||||
}
|
||||
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
//LOGI("move delta: %f (%f, %f), %d\n", moveDelta, dx, dy, state);
|
||||
}
|
||||
} else {
|
||||
// Wasn't active, and isn't active!
|
||||
state = State_None;
|
||||
}
|
||||
|
||||
updateFeedbackProgressAlpha(now);
|
||||
|
||||
wasActive = isActive;
|
||||
return TurnDelta(dx, -dy);
|
||||
}
|
||||
|
||||
void updateFeedbackProgressAlpha(float now) {
|
||||
const float MinAlphaValue = -0.05f;
|
||||
if (_canDestroy) {
|
||||
// Hack to test out fading in feedback circle
|
||||
const float since = now - _startTurnTime;
|
||||
if (state == State_Deciding) {
|
||||
const float wantedAlpha = since / (0.001f*RemovalMilliseconds);
|
||||
_holder->alpha = wantedAlpha * wantedAlpha;
|
||||
} else {
|
||||
if (state == State_Destroy) {
|
||||
_holder->alpha = calcNewAlpha(_holder->alpha, 1);
|
||||
} else if (state == State_Turn || state == State_None) {
|
||||
_holder->alpha = calcNewAlpha(_holder->alpha, 0);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
_holder->alpha = MinAlphaValue;
|
||||
}
|
||||
//LOGI("state: %d, canDestroy: %d %d\n", state, _canDestroy, _forceCanUse);
|
||||
//LOGI("alpha: %f\n", _holder->alpha);
|
||||
}
|
||||
|
||||
bool isInsideArea(float x, float y) {
|
||||
return _area.isInside(x, y);
|
||||
}
|
||||
|
||||
int mode;
|
||||
|
||||
static float getSpeedSquared(Entity* m) {
|
||||
const float xd = m->x - m->xo;
|
||||
const float yd = m->y - m->yo;
|
||||
const float zd = m->z - m->zo;
|
||||
const float speedSquared = xd*xd + yd*yd + zd*zd;
|
||||
return speedSquared;
|
||||
}
|
||||
|
||||
void render(float alpha) {
|
||||
if (_options->isJoyTouchArea) {
|
||||
fill( (int) (Gui::InvGuiScale * joyTouchArea._x0),
|
||||
(int) (Gui::InvGuiScale * joyTouchArea._y0),
|
||||
(int) (Gui::InvGuiScale * joyTouchArea._x1),
|
||||
(int) (Gui::InvGuiScale * joyTouchArea._y1), 0x40000000);//0x20ffffff);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation for the IBuildInput part
|
||||
//
|
||||
virtual bool tickBuild(Player* player, BuildActionIntention* bai) {
|
||||
_lastPlayer = player;
|
||||
|
||||
if (state == State_Destroy) {
|
||||
if (!_sentFirstRemove) {
|
||||
*bai = BuildActionIntention((_forceCanUse?0:BuildActionIntention::BAI_FIRSTREMOVE) | BuildActionIntention::BAI_INTERACT);
|
||||
_sentFirstRemove = true;
|
||||
} else {
|
||||
*bai = BuildActionIntention((_forceCanUse?0:BuildActionIntention::BAI_REMOVE) | BuildActionIntention::BAI_INTERACT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rewind the queue, in case someone has used it up before
|
||||
Multitouch::rewind();
|
||||
const float now = getTimeS();
|
||||
allowPicking = false;
|
||||
bool handled = false;
|
||||
|
||||
while (Multitouch::next()) {
|
||||
MouseAction& m = Multitouch::getEvent();
|
||||
if (m.action == MouseAction::ACTION_MOVE) continue;
|
||||
|
||||
int areaId = _model.getPointerId(m.x, m.y, m.pointerId);
|
||||
if (areaId != AREA_TURN) continue;
|
||||
|
||||
allowPicking = true;
|
||||
//LOGI("down? %d, up? %d (%d, %d)\n", z && (m.data == MouseAction::DATA_DOWN), z && (m.data == MouseAction::DATA_UP), m.x, m.y);
|
||||
|
||||
if (_totalMoveDelta <= MaxBuildMovement && (m.data == MouseAction::DATA_UP && !handled)) {
|
||||
const float since = now - _lastBuildDownTime;
|
||||
//LOGI("move: (%d) %.2f - %f\n", state, _totalMoveDelta, since);
|
||||
if (state <= State_Deciding) {
|
||||
if (since >= 0.0f && since < 0.25f) {
|
||||
// We've pressed and released in haste; Let's build!
|
||||
*bai = BuildActionIntention(BuildActionIntention::BAI_BUILD | BuildActionIntention::BAI_ATTACK);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
state = State_None;
|
||||
} else if (m.data == MouseAction::DATA_DOWN) {
|
||||
_lastBuildDownTime = now;
|
||||
_buildMovement = 0;
|
||||
state = State_Deciding;
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool allowPicking;
|
||||
float alpha;
|
||||
SmoothFloat smoothAlpha;
|
||||
|
||||
RectangleArea screenArea;
|
||||
RectangleArea moveArea;
|
||||
RectangleArea joyTouchArea;
|
||||
RectangleArea inventoryArea;
|
||||
RectangleArea pauseArea;
|
||||
|
||||
private:
|
||||
IInputHolder* _holder;
|
||||
|
||||
// Turn
|
||||
int cid;
|
||||
float cxO, cyO;
|
||||
bool wasActive;
|
||||
|
||||
TouchAreaModel _model;
|
||||
IncludeExcludeArea _area;
|
||||
|
||||
bool _decidedTurnMode;
|
||||
|
||||
float _startTurnTime;
|
||||
float _totalMoveDelta;
|
||||
float _maxMovement;
|
||||
float _sensitivity;
|
||||
|
||||
Player* _lastPlayer;
|
||||
|
||||
// Build
|
||||
float _lastBuildDownTime;
|
||||
float _buildMovement;
|
||||
bool _sentFirstRemove;
|
||||
bool _canDestroy;
|
||||
bool _forceCanUse;
|
||||
|
||||
int state;
|
||||
static const int State_None = 0;
|
||||
static const int State_Deciding = 1;
|
||||
static const int State_Turn = 2;
|
||||
static const int State_Destroy = 3;
|
||||
static const int State_Build = 4; // Will never happen
|
||||
|
||||
static const int MaxBuildMovement = 20;
|
||||
static const int RemovalMilliseconds = 400;
|
||||
|
||||
static const int AREA_TURN = 100;
|
||||
Options* _options;
|
||||
};
|
||||
|
||||
class Minecraft;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( disable : 4355 ) // 'this' pointer in initialization list which is perfectly legal
|
||||
#endif
|
||||
|
||||
class TouchInputHolder: public IInputHolder
|
||||
{
|
||||
public:
|
||||
TouchInputHolder(Minecraft* mc, Options* options)
|
||||
: _mc(mc),
|
||||
_move(mc, options),
|
||||
_turnBuild(UnifiedTurnBuild::MODE_DELTA, mc->width, mc->height, (float)MovementLimit, 1, this, mc)
|
||||
{
|
||||
onConfigChanged(createConfig(mc));
|
||||
}
|
||||
~TouchInputHolder() {
|
||||
}
|
||||
|
||||
virtual void onConfigChanged(const Config& c) {
|
||||
_move.onConfigChanged(c);
|
||||
_turnBuild.moveArea = _move.getRectangleArea();
|
||||
#ifdef __APPLE__
|
||||
_turnBuild.pauseArea = _move.getPauseRectangleArea();
|
||||
#endif
|
||||
_turnBuild.inventoryArea = _mc->gui.getRectangleArea( _mc->options.isLeftHanded? 1 : -1 );
|
||||
_turnBuild.setSensitivity(c.options->isJoyTouchArea? 1.8f : 1.0f);
|
||||
((ITurnInput*)&_turnBuild)->onConfigChanged(c);
|
||||
}
|
||||
|
||||
virtual bool allowPicking() {
|
||||
const int* pointerIds;
|
||||
int pointerCount = Multitouch::getActivePointerIds(&pointerIds);
|
||||
for (int i = 0; i < pointerCount; ++i) {
|
||||
int p = pointerIds[i];
|
||||
const float x = Multitouch::getX(p);
|
||||
const float y = Multitouch::getY(p);
|
||||
|
||||
if (_turnBuild.isInsideArea(x, y)) {
|
||||
mousex = x;
|
||||
mousey = y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// return _turnBuild.allowPicking;
|
||||
}
|
||||
|
||||
virtual void render(float alpha) {
|
||||
_turnBuild.render(alpha);
|
||||
}
|
||||
|
||||
virtual IMoveInput* getMoveInput() { return &_move; }
|
||||
virtual ITurnInput* getTurnInput() { return &_turnBuild; }
|
||||
virtual IBuildInput* getBuildInput() { return &_turnBuild; }
|
||||
|
||||
private:
|
||||
TouchscreenInput_TestFps _move;
|
||||
UnifiedTurnBuild _turnBuild;
|
||||
|
||||
Minecraft* _mc;
|
||||
|
||||
static const int MovementLimit = 200; // per update
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchInputHolder_H__*/
|
||||
88
src/client/player/input/touchscreen/TouchTurnInput.h
Executable file
88
src/client/player/input/touchscreen/TouchTurnInput.h
Executable file
@@ -0,0 +1,88 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchTurnInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchTurnInput_H__
|
||||
|
||||
#include "../ITurnInput.h"
|
||||
#include "TouchAreaModel.h"
|
||||
#include "../../../../platform/input/Multitouch.h"
|
||||
|
||||
class TouchTurnInput: public ITurnInput
|
||||
{
|
||||
public:
|
||||
static const int MODE_OFFSET = 1;
|
||||
static const int MODE_DELTA = 2;
|
||||
|
||||
TouchTurnInput(int mode_)
|
||||
: mode(mode_),
|
||||
cxO(0), cyO(0),
|
||||
wasActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
TurnDelta getTurnDelta() {
|
||||
float dx = 0, dy = 0;
|
||||
|
||||
float cx = 0;
|
||||
float cy = 0;
|
||||
bool isActive = false;
|
||||
|
||||
const int* pointerIds;
|
||||
int pointerCount = Multitouch::getActivePointerIds(&pointerIds);
|
||||
for (int i = 0; i < pointerCount; ++i) {
|
||||
int p = pointerIds[i];
|
||||
int x = Multitouch::getX(p);
|
||||
int y = Multitouch::getY(p);
|
||||
int areaId = _model.getPointerId(x, y, p);
|
||||
|
||||
if (areaId == AREA_TURN) {
|
||||
isActive = true;
|
||||
cx = (float)x * 0.5f;
|
||||
cy = (float)y * -0.5f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (MODE_OFFSET == mode) {
|
||||
//float dt = getDeltaTime();
|
||||
//const float MaxTurnX = 250.0f;
|
||||
//const float MaxTurnY = 200.0f;
|
||||
//float cx = isActive? Controller::getX(cid) : cxO * 0.7f;
|
||||
//float cy = isActive? Controller::getY(cid) : cyO * 0.7f;
|
||||
//dx = linearTransform( cx, 0.1f, MaxTurnX ) * dt;
|
||||
//dy = linearTransform( cy, 0.1f, MaxTurnY ) * dt;
|
||||
//cxO = cx;
|
||||
//cyO = cy;
|
||||
} else
|
||||
if (MODE_DELTA == mode && (wasActive || isActive)) {
|
||||
// const float dt = getDeltaTime();
|
||||
// const float MaxTurnX = 100.0f;
|
||||
// const float MaxTurnY = 100.0f;
|
||||
const float DeadZone = 0;//0.25f * dt;//0.02f;
|
||||
|
||||
if (!wasActive) {
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
}
|
||||
if (isActive) {
|
||||
dx = linearTransform(cx - cxO, DeadZone);// * MaxTurnX;
|
||||
dy = linearTransform(cy - cyO, DeadZone);// * MaxTurnY;
|
||||
cxO = cx;
|
||||
cyO = cy;
|
||||
}
|
||||
}
|
||||
|
||||
wasActive = isActive;
|
||||
return TurnDelta(dx, -dy);
|
||||
}
|
||||
|
||||
int mode;
|
||||
private:
|
||||
int cid;
|
||||
float cxO, cyO;
|
||||
bool wasActive;
|
||||
|
||||
TouchAreaModel _model;
|
||||
|
||||
static const int AREA_TURN = 100;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchTurnInput_H__*/
|
||||
509
src/client/player/input/touchscreen/TouchscreenInput.cpp
Executable file
509
src/client/player/input/touchscreen/TouchscreenInput.cpp
Executable file
@@ -0,0 +1,509 @@
|
||||
#include "TouchscreenInput.h"
|
||||
#include "../../../Options.h"
|
||||
#include "../../../../platform/input/Multitouch.h"
|
||||
#include "../../../gui/Gui.h"
|
||||
#include "../../../renderer/Tesselator.h"
|
||||
#include "../../../../world/entity/player/Player.h"
|
||||
|
||||
#include "../../../Minecraft.h"
|
||||
#include "../../../../platform/log.h"
|
||||
#include "../../../renderer/Textures.h"
|
||||
#include "../../../sound/SoundEngine.h"
|
||||
|
||||
static const int AREA_DPAD_FIRST = 100;
|
||||
static const int AREA_DPAD_N = 100;
|
||||
static const int AREA_DPAD_S = 101;
|
||||
static const int AREA_DPAD_W = 102;
|
||||
static const int AREA_DPAD_E = 103;
|
||||
static const int AREA_DPAD_C = 104;
|
||||
static const int AREA_PAUSE = 105;
|
||||
|
||||
static int cPressed = 0;
|
||||
static int cReleased = 0;
|
||||
static int cDiscreet = 0;
|
||||
static int cPressedPause = 0;
|
||||
static int cReleasedPause = 0;
|
||||
//static const int AREA_DPAD_N_JUMP = 105;
|
||||
|
||||
//
|
||||
// TouchscreenInput_TestFps
|
||||
//
|
||||
|
||||
static void Copy(int n, float* x, float* y, float* dx, float* dy) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
dx[i] = x[i];
|
||||
dy[i] = y[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void Translate(int n, float* x, float* y, float xt, float yt) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
x[i] += xt;
|
||||
y[i] += yt;
|
||||
}
|
||||
}
|
||||
|
||||
static void Scale(int n, float* x, float* y, float xt, float yt) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
x[i] *= xt;
|
||||
y[i] *= yt;
|
||||
}
|
||||
}
|
||||
|
||||
static void Transformed(int n, float* x, float* y, float* dx, float* dy, float xt, float yt, float sx=1.0f, float sy=1.0f) {
|
||||
Copy(n, x, y, dx, dy);
|
||||
Scale(n, dx, dy, sx, sy);
|
||||
Translate(n, dx, dy, xt, yt);
|
||||
|
||||
//for (int i = 0; i < n; ++i) {
|
||||
// LOGI("%d. (%f, %f)\n", i, dx[i], dy[i]);
|
||||
//}
|
||||
}
|
||||
|
||||
TouchscreenInput_TestFps::TouchscreenInput_TestFps( Minecraft* mc, Options* options )
|
||||
: _minecraft(mc),
|
||||
_options(options),
|
||||
_northJump(false),
|
||||
_forward(false),
|
||||
_boundingRectangle(0, 0, 1, 1),
|
||||
_pressedJump(false),
|
||||
_pauseIsDown(false),
|
||||
_sneakTapTime(-999),
|
||||
aLeft(0),
|
||||
aRight(0),
|
||||
aUp(0),
|
||||
aDown(0),
|
||||
aJump(0),
|
||||
aUpLeft(0),
|
||||
aUpRight(0),
|
||||
_allowHeightChange(false)
|
||||
{
|
||||
releaseAllKeys();
|
||||
onConfigChanged( createConfig(mc) );
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
const int alpha = 128;
|
||||
t.color( 0xc0c0c0, alpha); cPressed = t.getColor();
|
||||
t.color( 0xffffff, alpha); cReleased = t.getColor();
|
||||
t.color( 0xffffff, alpha / 4); cDiscreet = t.getColor();
|
||||
t.color( 0xc0c0c0, 80); cPressedPause=t.getColor();
|
||||
t.color( 0xffffff, 80); cReleasedPause=t.getColor();
|
||||
}
|
||||
|
||||
TouchscreenInput_TestFps::~TouchscreenInput_TestFps() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void TouchscreenInput_TestFps::clear() {
|
||||
_model.clear();
|
||||
|
||||
delete aUpLeft; aUpLeft = NULL; // @todo: SAFEDEL
|
||||
delete aUpRight; aUpRight = NULL;
|
||||
}
|
||||
|
||||
bool TouchscreenInput_TestFps::isButtonDown(int areaId) {
|
||||
return _buttons[areaId - AREA_DPAD_FIRST];
|
||||
}
|
||||
|
||||
|
||||
void TouchscreenInput_TestFps::onConfigChanged(const Config& c) {
|
||||
clear();
|
||||
|
||||
const float w = (float)c.width;
|
||||
const float h = (float)c.height;
|
||||
|
||||
/*
|
||||
// Code for "Move when touching left side of the screen"
|
||||
float x0[] = { 0, w * 0.3f, w * 0.3f, 0 };
|
||||
float y0[] = { 0, 0, h-32, h-32 };
|
||||
|
||||
_model.addArea(AREA_MOVE, new RectangleArea(0, 0, w*0.3f, h-32));
|
||||
*/
|
||||
|
||||
// Code for "D-pad with jump in center"
|
||||
float Bw = w * 0.11f;//0.08f;
|
||||
float Bh = Bw;//0.15f;
|
||||
|
||||
// If too large (like playing on Tablet)
|
||||
PixelCalc& pc = _minecraft->pixelCalc;
|
||||
if (pc.pixelsToMillimeters(Bw) > 14) {
|
||||
Bw = Bh = pc.millimetersToPixels(14);
|
||||
}
|
||||
// temp data
|
||||
float xx;
|
||||
float yy;
|
||||
|
||||
const float BaseY = -8 + h - 3.0f * Bh;
|
||||
const float BaseX = _options->isLeftHanded? -8 + w - 3 * Bw
|
||||
: 8 + 0;
|
||||
// Setup the bounding rectangle
|
||||
_boundingRectangle = RectangleArea(BaseX, BaseY, BaseX + 3 * Bw, BaseY + 3 * Bh);
|
||||
|
||||
xx = BaseX + Bw; yy = BaseY;
|
||||
_model.addArea(AREA_DPAD_N, aUp = new RectangleArea(xx, yy, xx+Bw, yy+Bh));
|
||||
xx = BaseX;
|
||||
aUpLeft = new RectangleArea(xx, yy, xx+Bw, yy+Bh);
|
||||
xx = BaseX + 2 * Bw;
|
||||
aUpRight = new RectangleArea(xx, yy, xx+Bw, yy+Bh);
|
||||
|
||||
xx = BaseX + Bw; yy = BaseY + Bh;
|
||||
_model.addArea(AREA_DPAD_C, aJump = new RectangleArea(xx, yy, xx+Bw, yy+Bh));
|
||||
|
||||
xx = BaseX + Bw; yy = BaseY + 2 * Bh;
|
||||
_model.addArea(AREA_DPAD_S, aDown = new RectangleArea(xx, yy, xx+Bw, yy+Bh));
|
||||
|
||||
xx = BaseX; yy = BaseY + Bh;
|
||||
_model.addArea(AREA_DPAD_W, aLeft = new RectangleArea(xx, yy, xx+Bw, yy+Bh));
|
||||
|
||||
xx = BaseX + 2 * Bw; yy = BaseY + Bh;
|
||||
_model.addArea(AREA_DPAD_E, aRight = new RectangleArea(xx, yy, xx+Bw, yy+Bh));
|
||||
|
||||
#ifdef __APPLE__
|
||||
float maxPixels = _minecraft->pixelCalc.millimetersToPixels(10);
|
||||
float btnSize = Mth::Min(18 * Gui::GuiScale, maxPixels);
|
||||
_model.addArea(AREA_PAUSE, aPause = new RectangleArea(w - 4 - btnSize,
|
||||
4,
|
||||
w - 4,
|
||||
4 + btnSize));
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
//rebuild();
|
||||
}
|
||||
|
||||
void TouchscreenInput_TestFps::setKey( int key, bool state )
|
||||
{
|
||||
#ifdef WIN32
|
||||
//LOGI("key: %d, %d\n", key, state);
|
||||
|
||||
int id = -1;
|
||||
if (key == _options->keyUp.key) id = KEY_UP;
|
||||
if (key == _options->keyDown.key) id = KEY_DOWN;
|
||||
if (key == _options->keyLeft.key) id = KEY_LEFT;
|
||||
if (key == _options->keyRight.key) id = KEY_RIGHT;
|
||||
if (key == _options->keyJump.key) id = KEY_JUMP;
|
||||
if (key == _options->keySneak.key) id = KEY_SNEAK;
|
||||
if (key == _options->keyCraft.key) id = KEY_CRAFT;
|
||||
if (id >= 0) {
|
||||
_keys[id] = state;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TouchscreenInput_TestFps::releaseAllKeys()
|
||||
{
|
||||
xa = 0;
|
||||
ya = 0;
|
||||
|
||||
for (int i = 0; i<8; ++i)
|
||||
_buttons[i] = false;
|
||||
#ifdef WIN32
|
||||
for (int i = 0; i<NumKeys; ++i)
|
||||
_keys[i] = false;
|
||||
#endif
|
||||
_pressedJump = false;
|
||||
_allowHeightChange = false;
|
||||
}
|
||||
|
||||
void TouchscreenInput_TestFps::tick( Player* player )
|
||||
{
|
||||
xa = 0;
|
||||
ya = 0;
|
||||
jumping = false;
|
||||
|
||||
//bool gotEvent = false;
|
||||
bool heldJump = false;
|
||||
bool tmpForward = false;
|
||||
bool tmpNorthJump = false;
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
_buttons[i] = false;
|
||||
|
||||
const int* pointerIds;
|
||||
int pointerCount = Multitouch::getActivePointerIdsThisUpdate(&pointerIds);
|
||||
for (int i = 0; i < pointerCount; ++i) {
|
||||
int p = pointerIds[i];
|
||||
int x = Multitouch::getX(p);
|
||||
int y = Multitouch::getY(p);
|
||||
|
||||
if (_boundingRectangle.isInside((float)x, (float)y) && _forward && !isChangingFlightHeight)
|
||||
{
|
||||
float angle = Mth::PI + Mth::atan2(y - _boundingRectangle.centerY(), x - _boundingRectangle.centerX());
|
||||
ya = Mth::sin(angle);
|
||||
xa = Mth::cos(angle);
|
||||
tmpForward = true;
|
||||
}
|
||||
|
||||
int areaId = _model.getPointerId(x, y, p);
|
||||
if (areaId < AREA_DPAD_FIRST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool setButton = false;
|
||||
|
||||
if (Multitouch::isPressed(p))
|
||||
_allowHeightChange = (areaId == AREA_DPAD_C);
|
||||
|
||||
if (areaId == AREA_DPAD_C)
|
||||
{
|
||||
setButton = true;
|
||||
heldJump = true;
|
||||
// If we're in water or pressed down on the button: jump
|
||||
if (player->isInWater()) {
|
||||
jumping = true;
|
||||
}
|
||||
else if (Multitouch::isPressed(p)) {
|
||||
jumping = true;
|
||||
} // Or if we are walking forward, jump while going forward!
|
||||
else if (_forward && !player->abilities.flying) {
|
||||
areaId = AREA_DPAD_N;
|
||||
tmpNorthJump = true;
|
||||
//jumping = true;
|
||||
ya += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (areaId == AREA_DPAD_N)
|
||||
{
|
||||
setButton = true;
|
||||
if (player->isInWater())
|
||||
jumping = true;
|
||||
else if (!isChangingFlightHeight)
|
||||
tmpForward = true;
|
||||
ya += 1;
|
||||
}
|
||||
else if (areaId == AREA_DPAD_S && !_forward)
|
||||
{
|
||||
setButton = true;
|
||||
ya -= 1;
|
||||
/*
|
||||
if (Multitouch::isReleased(p)) {
|
||||
float now = getTimeS();
|
||||
if (now - _sneakTapTime < 0.4f) {
|
||||
ya += 1;
|
||||
sneaking = !sneaking;
|
||||
player->setSneaking(sneaking);
|
||||
_sneakTapTime = -1;
|
||||
} else {
|
||||
_sneakTapTime = now;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (areaId == AREA_DPAD_W && !_forward)
|
||||
{
|
||||
setButton = true;
|
||||
xa += 1;
|
||||
}
|
||||
else if (areaId == AREA_DPAD_E && !_forward)
|
||||
{
|
||||
setButton = true;
|
||||
xa -= 1;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
else if (areaId == AREA_PAUSE) {
|
||||
if (Multitouch::isReleased(p)) {
|
||||
_minecraft->soundEngine->playUI("random.click", 1, 1);
|
||||
_minecraft->screenChooser.setScreen(SCREEN_PAUSE);
|
||||
}
|
||||
}
|
||||
#endif /*__APPLE__*/
|
||||
_buttons[areaId - AREA_DPAD_FIRST] = setButton;
|
||||
}
|
||||
|
||||
_forward = tmpForward;
|
||||
|
||||
// Only jump once at a time
|
||||
if (tmpNorthJump) {
|
||||
if (!_northJump)
|
||||
jumping = true;
|
||||
_northJump = true;
|
||||
}
|
||||
else _northJump = false;
|
||||
|
||||
isChangingFlightHeight = false;
|
||||
wantUp = isButtonDown(AREA_DPAD_N) && (_allowHeightChange & (_pressedJump | wantUp));
|
||||
wantDown = isButtonDown(AREA_DPAD_S) && (_allowHeightChange & (_pressedJump | wantDown));
|
||||
if (player->abilities.flying && (wantUp || wantDown || (heldJump && !_forward)))
|
||||
{
|
||||
isChangingFlightHeight = true;
|
||||
ya = 0;
|
||||
}
|
||||
_renderFlightImage = player->abilities.flying;
|
||||
|
||||
#ifdef WIN32
|
||||
if (_keys[KEY_UP]) ya++;
|
||||
if (_keys[KEY_DOWN]) ya--;
|
||||
if (_keys[KEY_LEFT]) xa++;
|
||||
if (_keys[KEY_RIGHT]) xa--;
|
||||
if (_keys[KEY_JUMP]) jumping = true;
|
||||
//sneaking = _keys[KEY_SNEAK];
|
||||
if (_keys[KEY_CRAFT])
|
||||
player->startCrafting((int)player->x, (int)player->y, (int)player->z, Recipe::SIZE_2X2);
|
||||
#endif
|
||||
|
||||
if (sneaking) {
|
||||
xa *= 0.3f;
|
||||
ya *= 0.3f;
|
||||
}
|
||||
//printf("\n>- %f %f\n", xa, ya);
|
||||
_pressedJump = heldJump;
|
||||
}
|
||||
|
||||
static void drawRectangleArea(Tesselator& t, RectangleArea* a, int ux, int vy, float ssz = 64.0f) {
|
||||
const float pm = 1.0f / 256.0f;
|
||||
const float sz = ssz * pm;
|
||||
const float uu = (float)(ux) * pm;
|
||||
const float vv = (float)(vy) * pm;
|
||||
const float x0 = a->_x0 * Gui::InvGuiScale;
|
||||
const float x1 = a->_x1 * Gui::InvGuiScale;
|
||||
const float y0 = a->_y0 * Gui::InvGuiScale;
|
||||
const float y1 = a->_y1 * Gui::InvGuiScale;
|
||||
|
||||
t.vertexUV(x0, y1, 0, uu, vv+sz);
|
||||
t.vertexUV(x1, y1, 0, uu+sz,vv+sz);
|
||||
t.vertexUV(x1, y0, 0, uu+sz,vv);
|
||||
t.vertexUV(x0, y0, 0, uu, vv);
|
||||
}
|
||||
|
||||
static void drawPolygonArea(Tesselator& t, PolygonArea* a, int x, int y) {
|
||||
float pm = 1.0f / 256.0f;
|
||||
float sz = 64.0f * pm;
|
||||
float uu = (float)(x) * pm;
|
||||
float vv = (float)(y) * pm;
|
||||
|
||||
float uvs[] = {uu, vv, uu+sz, vv, uu+sz, vv+sz, uu, vv+sz};
|
||||
const int o = 0;
|
||||
|
||||
for (int j = 0; j < a->_numPoints; ++j) {
|
||||
t.vertexUV(a->_x[j] * Gui::InvGuiScale, a->_y[j] * Gui::InvGuiScale, 0, uvs[(o+j+j)&7], uvs[(o+j+j+1)&7]);
|
||||
}
|
||||
}
|
||||
|
||||
void TouchscreenInput_TestFps::render( float a ) {
|
||||
//return;
|
||||
|
||||
//static Stopwatch sw;
|
||||
//sw.start();
|
||||
|
||||
|
||||
//glColor4f2(1, 0, 1, 1.0f);
|
||||
//glDisable2(GL_CULL_FACE);
|
||||
glDisable2(GL_ALPHA_TEST);
|
||||
|
||||
glEnable2(GL_BLEND);
|
||||
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
_minecraft->textures->loadAndBindTexture("gui/gui.png");
|
||||
|
||||
//glDisable2(GL_TEXTURE_2D);
|
||||
|
||||
rebuild();
|
||||
//drawArrayVTC(_bufferId, 5 * 2 * 3, 24);
|
||||
|
||||
glDisable2(GL_BLEND);
|
||||
//glEnable2(GL_TEXTURE_2D);
|
||||
//glEnable2(GL_CULL_FACE);
|
||||
|
||||
//sw.stop();
|
||||
//sw.printEvery(100, "buttons");
|
||||
}
|
||||
|
||||
const RectangleArea& TouchscreenInput_TestFps::getRectangleArea()
|
||||
{
|
||||
return _boundingRectangle;
|
||||
}
|
||||
const RectangleArea& TouchscreenInput_TestFps::getPauseRectangleArea()
|
||||
{
|
||||
return *aPause;
|
||||
}
|
||||
|
||||
void TouchscreenInput_TestFps::rebuild() {
|
||||
if (_options->hideGui)
|
||||
return;
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
//LOGI("instance is: %p, %p, %p, %p, %p FOR %d\n", &t, aLeft, aRight, aUp, aDown, aJump, _bufferId);
|
||||
//t.setAccessMode(Tesselator::ACCESS_DYNAMIC);
|
||||
t.begin();
|
||||
|
||||
const int imageU = 0;
|
||||
const int imageV = 107;
|
||||
const int imageSize = 26;
|
||||
|
||||
bool northDiagonals = !isChangingFlightHeight && (_northJump || _forward);
|
||||
|
||||
// render left button
|
||||
if (northDiagonals || isChangingFlightHeight) t.colorABGR(cDiscreet);
|
||||
else if (isButtonDown(AREA_DPAD_W)) t.colorABGR(cPressed);
|
||||
else t.colorABGR(cReleased);
|
||||
drawRectangleArea(t, aLeft, imageU + imageSize, imageV, (float)imageSize);
|
||||
|
||||
// render right button
|
||||
if (northDiagonals || isChangingFlightHeight) t.colorABGR(cDiscreet);
|
||||
else if (isButtonDown(AREA_DPAD_E)) t.colorABGR(cPressed);
|
||||
else t.colorABGR(cReleased);
|
||||
drawRectangleArea(t, aRight, imageU + imageSize * 3, imageV, (float)imageSize);
|
||||
|
||||
// render forward button
|
||||
if (isButtonDown(AREA_DPAD_N)) t.colorABGR(cPressed);
|
||||
else t.colorABGR(cReleased);
|
||||
if (isChangingFlightHeight)
|
||||
{
|
||||
drawRectangleArea(t, aUp, imageU + imageSize * 2, imageV + imageSize, (float)imageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRectangleArea(t, aUp, imageU, imageV, (float)imageSize);
|
||||
}
|
||||
|
||||
// render diagonals, if available
|
||||
if (northDiagonals)
|
||||
{
|
||||
t.colorABGR(cReleased);
|
||||
drawRectangleArea(t, aUpLeft, imageU, imageV + imageSize, (float)imageSize);
|
||||
drawRectangleArea(t, aUpRight, imageU + imageSize, imageV + imageSize, (float)imageSize);
|
||||
}
|
||||
|
||||
// render backwards button
|
||||
if (northDiagonals) t.colorABGR(cDiscreet);
|
||||
else if (isButtonDown(AREA_DPAD_S)) t.colorABGR(cPressed);
|
||||
else t.colorABGR(cReleased);
|
||||
if (isChangingFlightHeight)
|
||||
{
|
||||
drawRectangleArea(t, aDown, imageU + imageSize * 3, imageV + imageSize, (float)imageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRectangleArea(t, aDown, imageU + imageSize * 2, imageV, (float)imageSize);
|
||||
}
|
||||
|
||||
// render jump / flight button
|
||||
if (_renderFlightImage && northDiagonals) t.colorABGR(cDiscreet);
|
||||
else if (isButtonDown(AREA_DPAD_C)) t.colorABGR(cPressed);
|
||||
else t.colorABGR(cReleased);
|
||||
if (_renderFlightImage)
|
||||
{
|
||||
drawRectangleArea(t, aJump, imageU + imageSize * 4, imageV + imageSize, (float)imageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRectangleArea(t, aJump, imageU + imageSize * 4, imageV, (float)imageSize);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (!_minecraft->screen) {
|
||||
if (isButtonDown(AREA_PAUSE)) t.colorABGR(cPressedPause);
|
||||
else t.colorABGR(cReleasedPause);
|
||||
|
||||
drawRectangleArea(t, aPause, 200, 64, 18.0f);
|
||||
}
|
||||
#endif /*__APPLE__*/
|
||||
//t.end(true, _bufferId);
|
||||
//return;
|
||||
|
||||
t.draw();
|
||||
//RenderChunk _render = t.end(true, _bufferId);
|
||||
//t.setAccessMode(Tesselator::ACCESS_STATIC);
|
||||
//_bufferId = _render.vboId;
|
||||
}
|
||||
79
src/client/player/input/touchscreen/TouchscreenInput.h
Executable file
79
src/client/player/input/touchscreen/TouchscreenInput.h
Executable file
@@ -0,0 +1,79 @@
|
||||
#ifndef NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchscreenInput_H__
|
||||
#define NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchscreenInput_H__
|
||||
|
||||
//package net.minecraft.client.player;
|
||||
|
||||
#include "../IMoveInput.h"
|
||||
#include "../../../gui/GuiComponent.h"
|
||||
#include "TouchAreaModel.h"
|
||||
#include "../../../renderer/RenderChunk.h"
|
||||
|
||||
class Options;
|
||||
class Player;
|
||||
class Minecraft;
|
||||
class PolygonArea;
|
||||
|
||||
// @todo: extract a separate MoveInput (-> merge XperiaPlayInput)
|
||||
class TouchscreenInput_TestFps: public IMoveInput,
|
||||
public GuiComponent
|
||||
{
|
||||
public:
|
||||
static const int KEY_UP = 0;
|
||||
static const int KEY_DOWN = 1;
|
||||
static const int KEY_LEFT = 2;
|
||||
static const int KEY_RIGHT = 3;
|
||||
static const int KEY_JUMP = 4;
|
||||
static const int KEY_SNEAK = 5;
|
||||
static const int KEY_CRAFT = 6;
|
||||
static const int NumKeys = 7;
|
||||
|
||||
TouchscreenInput_TestFps(Minecraft* mc, Options* options);
|
||||
~TouchscreenInput_TestFps();
|
||||
|
||||
void onConfigChanged(const Config& c);
|
||||
|
||||
void tick(Player* player);
|
||||
void render(float a);
|
||||
|
||||
void setKey(int key, bool state);
|
||||
void releaseAllKeys();
|
||||
|
||||
const RectangleArea& getRectangleArea();
|
||||
const RectangleArea& getPauseRectangleArea();
|
||||
|
||||
private:
|
||||
void clear();
|
||||
|
||||
RectangleArea _boundingRectangle;
|
||||
|
||||
bool _keys[NumKeys];
|
||||
Options* _options;
|
||||
|
||||
bool _pressedJump;
|
||||
bool _forward;
|
||||
bool _northJump;
|
||||
bool _renderFlightImage;
|
||||
TouchAreaModel _model;
|
||||
Minecraft* _minecraft;
|
||||
|
||||
RectangleArea* aLeft;
|
||||
RectangleArea* aRight;
|
||||
RectangleArea* aUp;
|
||||
RectangleArea* aDown;
|
||||
RectangleArea* aPause;
|
||||
//RectangleArea* aUpJump;
|
||||
RectangleArea* aJump;
|
||||
RectangleArea* aUpLeft;
|
||||
RectangleArea* aUpRight;
|
||||
bool _pauseIsDown;
|
||||
|
||||
RenderChunk _render;
|
||||
bool _allowHeightChange;
|
||||
float _sneakTapTime;
|
||||
|
||||
bool _buttons[8];
|
||||
bool isButtonDown(int areaId);
|
||||
void rebuild();
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER_INPUT_TOUCHSCREEN_TouchscreenInput_H__*/
|
||||
Reference in New Issue
Block a user