aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/BoatItem.cpp
blob: 3499bc02b50dcff0958361e4f82ba03cf8c13220 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "stdafx.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.entity.item.h"
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.tile.h"
#include "net.minecraft.world.phys.h"
#include "ItemInstance.h"
#include "BoatItem.h"

BoatItem::BoatItem(int id) : Item( id )
{
	this->maxStackSize = 1;
}

bool BoatItem::TestUse(Level *level, shared_ptr<Player> player)
{
	// 4J-PB - added for tooltips to test use
	// 4J TODO really we should have the crosshair hitresult telling us if it hit water, and at what distance, so we don't need to do this again
	// if the player happens to have a boat in their hand

	float xRot = player->xRotO + (player->xRot - player->xRotO);
	float yRot = player->yRotO + (player->yRot - player->yRotO);

	double x = player->xo + (player->x - player->xo);
	double y = player->yo + (player->y - player->yo) + 1.62 - player->heightOffset;
	double z = player->zo + (player->z - player->zo);

	Vec3 *from = Vec3::newTemp(x, y, z);

	float yCos = Mth::cos(-yRot * Mth::RAD_TO_GRAD - PI);
	float ySin = Mth::sin(-yRot * Mth::RAD_TO_GRAD - PI);
	float xCos = -Mth::cos(-xRot * Mth::RAD_TO_GRAD);
	float xSin = Mth::sin(-xRot * Mth::RAD_TO_GRAD);

	float xa = ySin * xCos;
	float ya = xSin;
	float za = yCos * xCos;

	double range = 5;
	Vec3 *to = from->add(xa * range, ya * range, za * range);
	HitResult *hr = level->clip(from, to, true);
	if (hr == NULL) return false;

	if (hr->type == HitResult::TILE)
	{
		delete hr;
		return true;
	}
	delete hr;
	return false;
}
shared_ptr<ItemInstance> BoatItem::use(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player)
{
	float a = 1;

	float xRot = player->xRotO + (player->xRot - player->xRotO) * a;
	float yRot = player->yRotO + (player->yRot - player->yRotO) * a;

	double x = player->xo + (player->x - player->xo) * a;
	double y = player->yo + (player->y - player->yo) * a + 1.62 - player->heightOffset;
	double z = player->zo + (player->z - player->zo) * a;

	Vec3 *from = Vec3::newTemp(x, y, z);

	float yCos = Mth::cos(-yRot * Mth::RAD_TO_GRAD - PI);
	float ySin = Mth::sin(-yRot * Mth::RAD_TO_GRAD - PI);
	float xCos = -Mth::cos(-xRot * Mth::RAD_TO_GRAD);
	float xSin = Mth::sin(-xRot * Mth::RAD_TO_GRAD);

	float xa = ySin * xCos;
	float ya = xSin;
	float za = yCos * xCos;

	double range = 5;
	Vec3 *to = from->add(xa * range, ya * range, za * range);
	HitResult *hr = level->clip(from, to, true);
	if (hr == NULL) return itemInstance;

	// check entity collision
	Vec3 *b = player->getViewVector(a);
	bool hitEntity = false;
	float overlap = 1;
	vector<shared_ptr<Entity> > *objects = level->getEntities(player, player->bb->expand(b->x * (range), b->y * (range), b->z * (range))->grow(overlap, overlap, overlap));
	//for (int i = 0; i < objects.size(); i++) {
	for(AUTO_VAR(it, objects->begin()); it != objects->end(); ++it)
	{
		shared_ptr<Entity> e = *it; //objects.get(i);
		if (!e->isPickable()) continue;

		float rr = e->getPickRadius();
		AABB *bb = e->bb->grow(rr, rr, rr);
		if (bb->contains(from))
		{
			hitEntity = true;
		}
	}
	if (hitEntity)
	{
		return itemInstance;
	}

	if (hr->type == HitResult::TILE)
	{
		int xt = hr->x;
		int yt = hr->y;
		int zt = hr->z;

		if (!level->isClientSide) 
		{
			if (level->getTile(xt, yt, zt) == Tile::topSnow_Id) yt--;
			if( level->countInstanceOf(eTYPE_BOAT, true) < Level::MAX_XBOX_BOATS )		// 4J - added limit
			{
				level->addEntity( shared_ptr<Boat>( new Boat(level, xt + 0.5f, yt + 1.0f, zt + 0.5f) ) );
				if (!player->abilities.instabuild)
				{
					itemInstance->count--;
				}
			}
			else
			{
				// display a message to say max boats has been hit
				player->displayClientMessage(IDS_MAX_BOATS );
			}
		}
	}
	delete hr;

	return itemInstance;
}