TU19: merge Minecraft.World/AI

This commit is contained in:
Tropical 2026-03-21 15:10:07 -05:00
parent 4c30ef1e62
commit 7973172ae8
89 changed files with 1546 additions and 463 deletions

View file

@ -0,0 +1,14 @@
#include "../../Platform/stdafx.h"
#include "Attribute.h"
const int Attribute::AttributeNames[] = {
IDS_ATTRIBUTE_NAME_GENERIC_MAXHEALTH,
IDS_ATTRIBUTE_NAME_GENERIC_FOLLOWRANGE,
IDS_ATTRIBUTE_NAME_GENERIC_KNOCKBACKRESISTANCE,
IDS_ATTRIBUTE_NAME_GENERIC_MOVEMENTSPEED,
IDS_ATTRIBUTE_NAME_GENERIC_ATTACKDAMAGE,
IDS_ATTRIBUTE_NAME_HORSE_JUMPSTRENGTH,
IDS_ATTRIBUTE_NAME_ZOMBIE_SPAWNREINFORCEMENTS,
};
int Attribute::getName(eATTRIBUTE_ID id) { return AttributeNames[id]; }

View file

@ -0,0 +1,73 @@
#pragma once
class AttributeModifier;
// 4J: This ID is serialised into save data so new attributes must always be
// added after existing ones
enum eATTRIBUTE_ID {
// 1.6.4
eAttributeId_GENERIC_MAXHEALTH,
eAttributeId_GENERIC_FOLLOWRANGE,
eAttributeId_GENERIC_KNOCKBACKRESISTANCE,
eAttributeId_GENERIC_MOVEMENTSPEED,
eAttributeId_GENERIC_ATTACKDAMAGE,
eAttributeId_HORSE_JUMPSTRENGTH,
eAttributeId_ZOMBIE_SPAWNREINFORCEMENTS,
// 1.8+
// New attributes go here
eAttributeId_COUNT
};
class Attribute {
public:
static const int MAX_NAME_LENGTH = 64;
/**
* 4J: Changed this from a std::string name to an ID
* Gets the ID of this attribute, for serialization.
*
* @return Name of this attribute.
*/
virtual eATTRIBUTE_ID getId() = 0;
/**
* Sanitizes an attribute value, making sure it's not out of range and is an
* acceptable amount.
*
*
* @param value Value to sanitize.
* @return Sanitized value, safe for use.
*/
virtual double sanitizeValue(double value) = 0;
/**
* Get the default value of this attribute, to be used upon creation.
*
* @return Default value.
*/
virtual double getDefaultValue() = 0;
/**
* Checks if this attribute should be synced to the client.
*
* Attributes should be serverside only unless the client needs to know
* about it.
*
* @return True if the client should know about this attribute.
*/
virtual bool isClientSyncable() = 0;
// 4J: Added to retrieve std::string ID for attribute
static int getName(eATTRIBUTE_ID id);
protected:
static const int AttributeNames[];
};
#ifdef __ORBIS__
typedef std::unordered_map<eATTRIBUTE_ID, AttributeModifier*, std::hash<int>>
attrAttrModMap;
#else
typedef std::unordered_map<eATTRIBUTE_ID, AttributeModifier*> attrAttrModMap;
#endif

View file

@ -0,0 +1,24 @@
#pragma once
#include "AttributeModifier.h"
class AttributeInstance {
public:
virtual ~AttributeInstance() {}
virtual Attribute* getAttribute() = 0;
virtual double getBaseValue() = 0;
virtual void setBaseValue(double baseValue) = 0;
virtual double getValue() = 0;
virtual std::unordered_set<AttributeModifier*>* getModifiers(
int operation) = 0;
virtual void getModifiers(
std::unordered_set<AttributeModifier*>& result) = 0;
virtual AttributeModifier* getModifier(eMODIFIER_ID id) = 0;
virtual void addModifiers(
std::unordered_set<AttributeModifier*>* modifiers) = 0;
virtual void addModifier(AttributeModifier* modifier) = 0;
virtual void removeModifier(AttributeModifier* modifier) = 0;
virtual void removeModifier(eMODIFIER_ID id) = 0;
virtual void removeModifiers() = 0;
};

View file

@ -0,0 +1,107 @@
#include "../../Platform/stdafx.h"
#include "AttributeModifier.h"
#include "../../Util/HtmlString.h"
void AttributeModifier::_init(eMODIFIER_ID id, const std::wstring name,
double amount, int operation) {
assert(operation < TOTAL_OPERATIONS);
this->amount = amount;
this->operation = operation;
this->name = name;
this->id = id;
this->serialize = true;
}
AttributeModifier::AttributeModifier(double amount, int operation) {
// Create an anonymous attribute
_init(eModifierId_ANONYMOUS, name, amount, operation);
}
AttributeModifier::AttributeModifier(eMODIFIER_ID id, double amount,
int operation) {
_init(id, name, amount, operation);
// Validate.notEmpty(name, "Modifier name cannot be empty");
// Validate.inclusiveBetween(0, TOTAL_OPERATIONS - 1, operation, "Invalid
// operation");
}
eMODIFIER_ID AttributeModifier::getId() { return id; }
std::wstring AttributeModifier::getName() { return name; }
int AttributeModifier::getOperation() { return operation; }
double AttributeModifier::getAmount() { return amount; }
bool AttributeModifier::isSerializable() { return serialize; }
AttributeModifier* AttributeModifier::setSerialize(bool serialize) {
this->serialize = serialize;
return this;
}
bool AttributeModifier::equals(AttributeModifier* modifier) {
if (this == modifier) return true;
if (modifier == NULL)
return false; //|| getClass() != o.getClass()) return false;
if (id != modifier->id) return false;
return true;
}
std::wstring AttributeModifier::toString() {
return L"";
/*return L"AttributeModifier{" +
L"amount=" + amount +
L", operation=" + operation +
L", name='" + name + '\'' +
L", id=" + id +
L", serialize=" + serialize +
L'}';*/
}
HtmlString AttributeModifier::getHoverText(eATTRIBUTE_ID attribute) {
double amount = getAmount();
double displayAmount;
if (getOperation() == AttributeModifier::OPERATION_MULTIPLY_BASE ||
getOperation() == AttributeModifier::OPERATION_MULTIPLY_TOTAL) {
displayAmount = getAmount() * 100.0f;
} else {
displayAmount = getAmount();
}
eMinecraftColour color;
if (amount > 0) {
color = eHTMLColor_9;
} else if (amount < 0) {
displayAmount *= -1;
color = eHTMLColor_c;
}
bool percentage = false;
switch (getOperation()) {
case AttributeModifier::OPERATION_ADDITION:
percentage = false;
break;
case AttributeModifier::OPERATION_MULTIPLY_BASE:
case AttributeModifier::OPERATION_MULTIPLY_TOTAL:
percentage = true;
break;
default:
// No other operations
assert(0);
}
wchar_t formatted[256];
swprintf(formatted, 256, L"%ls%d%ls %ls", (amount > 0 ? L"+" : L"-"),
(int)displayAmount, (percentage ? L"%" : L""),
app.GetString(Attribute::getName(attribute)));
return HtmlString(formatted, color);
}

View file

@ -0,0 +1,74 @@
#pragma once
/*
4J - Both modifier uuid and name have been replaced by an id enum. Note that we
have special value "eModifierId_ANONYMOUS" for attribute modifiers that
previously didn't have a fixed UUID and are never removed.
To all intents and purposes anonymous modifiers don't have an ID and so are
handled differently in some cases, for instance:
1. You can have multiple modifiers with the anonymous ID on a single
attribute instance
2. Anonymous modifiers can't be removed from attribute instance by ID
IMPORTANT: Saved out to file so don't change order. All new values should be
added at the end.
*/
class HtmlString;
enum eMODIFIER_ID {
eModifierId_ANONYMOUS = 0,
eModifierId_ITEM_BASEDAMAGE,
eModifierId_MOB_FLEEING,
eModifierId_MOB_SPRINTING,
eModifierId_MOB_ENDERMAN_ATTACKSPEED,
eModifierId_MOB_PIG_ATTACKSPEED,
eModifierId_MOB_WITCH_DRINKSPEED,
eModifierId_MOB_ZOMBIE_BABYSPEED,
eModifierId_POTION_DAMAGEBOOST,
eModifierId_POTION_HEALTHBOOST,
eModifierId_POTION_MOVESPEED,
eModifierId_POTION_MOVESLOWDOWN,
eModifierId_POTION_WEAKNESS,
eModifierId_COUNT,
};
class AttributeModifier {
public:
static const int OPERATION_ADDITION = 0;
static const int OPERATION_MULTIPLY_BASE = 1;
static const int OPERATION_MULTIPLY_TOTAL = 2;
static const int TOTAL_OPERATIONS = 3;
private:
double amount;
int operation;
std::wstring name;
eMODIFIER_ID id;
bool serialize;
void _init(eMODIFIER_ID id, const std::wstring name, double amount,
int operation);
public:
AttributeModifier(double amount, int operation);
AttributeModifier(eMODIFIER_ID id, double amount, int operation);
eMODIFIER_ID getId();
std::wstring getName();
int getOperation();
double getAmount();
bool isSerializable();
AttributeModifier* setSerialize(bool serialize);
bool equals(AttributeModifier* modifier);
std::wstring toString();
HtmlString getHoverText(
eATTRIBUTE_ID attribute); // 4J: Added to keep modifier readable
// std::string creation in one place
};

View file

@ -0,0 +1,20 @@
#include "../../Platform/stdafx.h"
#include "BaseAttribute.h"
BaseAttribute::BaseAttribute(eATTRIBUTE_ID id, double defaultValue) {
this->id = id;
this->defaultValue = defaultValue;
syncable = false;
}
eATTRIBUTE_ID BaseAttribute::getId() { return id; }
double BaseAttribute::getDefaultValue() { return defaultValue; }
bool BaseAttribute::isClientSyncable() { return syncable; }
BaseAttribute* BaseAttribute::setSyncable(bool syncable) {
this->syncable = syncable;
return this;
}

View file

@ -0,0 +1,19 @@
#pragma once
#include "Attribute.h"
class BaseAttribute : public Attribute {
private:
eATTRIBUTE_ID id;
double defaultValue;
bool syncable;
protected:
BaseAttribute(eATTRIBUTE_ID id, double defaultValue);
public:
virtual eATTRIBUTE_ID getId();
virtual double getDefaultValue();
virtual bool isClientSyncable();
virtual BaseAttribute* setSyncable(bool syncable);
};

View file

@ -0,0 +1,68 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
#include "BaseAttributeMap.h"
BaseAttributeMap::~BaseAttributeMap() {
for (AUTO_VAR(it, attributesById.begin()); it != attributesById.end();
++it) {
delete it->second;
}
}
AttributeInstance* BaseAttributeMap::getInstance(Attribute* attribute) {
return getInstance(attribute->getId());
}
AttributeInstance* BaseAttributeMap::getInstance(eATTRIBUTE_ID id) {
AUTO_VAR(it, attributesById.find(id));
if (it != attributesById.end()) {
return it->second;
} else {
return NULL;
}
}
void BaseAttributeMap::getAttributes(std::vector<AttributeInstance*>& atts) {
for (AUTO_VAR(it, attributesById.begin()); it != attributesById.end();
++it) {
atts.push_back(it->second);
}
}
void BaseAttributeMap::onAttributeModified(
ModifiableAttributeInstance* attributeInstance) {}
void BaseAttributeMap::removeItemModifiers(std::shared_ptr<ItemInstance> item) {
attrAttrModMap* modifiers = item->getAttributeModifiers();
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
AttributeInstance* attribute = getInstance(it->first);
AttributeModifier* modifier = it->second;
if (attribute != NULL) {
attribute->removeModifier(modifier);
}
delete modifier;
}
delete modifiers;
}
void BaseAttributeMap::addItemModifiers(std::shared_ptr<ItemInstance> item) {
attrAttrModMap* modifiers = item->getAttributeModifiers();
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
AttributeInstance* attribute = getInstance(it->first);
AttributeModifier* modifier = it->second;
if (attribute != NULL) {
attribute->removeModifier(modifier);
attribute->addModifier(new AttributeModifier(*modifier));
}
delete modifier;
}
delete modifiers;
}

View file

@ -0,0 +1,31 @@
#pragma once
class ModifiableAttributeInstance;
class BaseAttributeMap {
protected:
// unordered_map<Attribute *, AttributeInstance *> attributesByObject;
#ifdef __ORBIS__
std::unordered_map<eATTRIBUTE_ID, AttributeInstance*, std::hash<int> >
attributesById;
#else
std::unordered_map<eATTRIBUTE_ID, AttributeInstance*> attributesById;
#endif
public:
virtual ~BaseAttributeMap();
virtual AttributeInstance* getInstance(Attribute* attribute);
virtual AttributeInstance* getInstance(eATTRIBUTE_ID name);
virtual AttributeInstance* registerAttribute(Attribute* attribute) = 0;
virtual void getAttributes(std::vector<AttributeInstance*>& atts);
virtual void onAttributeModified(
ModifiableAttributeInstance* attributeInstance);
// 4J: Changed these into specialised functions for adding/removing the
// modifiers of an item (it's cleaner)
virtual void removeItemModifiers(std::shared_ptr<ItemInstance> item);
virtual void addItemModifiers(std::shared_ptr<ItemInstance> item);
};

View file

@ -0,0 +1,160 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
#include "ModifiableAttributeInstance.h"
ModifiableAttributeInstance::ModifiableAttributeInstance(
BaseAttributeMap* attributeMap, Attribute* attribute) {
this->attributeMap = attributeMap;
this->attribute = attribute;
dirty = true;
cachedValue = 0.0;
baseValue = attribute->getDefaultValue();
}
ModifiableAttributeInstance::~ModifiableAttributeInstance() {
for (int i = 0; i < AttributeModifier::TOTAL_OPERATIONS; i++) {
for (AUTO_VAR(it, modifiers[i].begin()); it != modifiers[i].end();
++it) {
// Delete all modifiers
delete *it;
}
}
}
Attribute* ModifiableAttributeInstance::getAttribute() { return attribute; }
double ModifiableAttributeInstance::getBaseValue() { return baseValue; }
void ModifiableAttributeInstance::setBaseValue(double baseValue) {
if (baseValue == this->getBaseValue()) return;
this->baseValue = baseValue;
setDirty();
}
// Returns a pointer to an internally managed vector of modifers by operation
std::unordered_set<AttributeModifier*>*
ModifiableAttributeInstance::getModifiers(int operation) {
return &modifiers[operation];
}
// Returns a pointer to a new vector of all modifiers
void ModifiableAttributeInstance::getModifiers(
std::unordered_set<AttributeModifier*>& result) {
for (int i = 0; i < AttributeModifier::TOTAL_OPERATIONS; i++) {
std::unordered_set<AttributeModifier*>* opModifiers = &modifiers[i];
for (AUTO_VAR(it, opModifiers->begin()); it != opModifiers->end();
++it) {
result.insert(*it);
}
}
}
AttributeModifier* ModifiableAttributeInstance::getModifier(eMODIFIER_ID id) {
AttributeModifier* modifier = NULL;
AUTO_VAR(it, modifierById.find(id));
if (it != modifierById.end()) {
modifier = it->second;
}
return modifier;
}
void ModifiableAttributeInstance::addModifiers(
std::unordered_set<AttributeModifier*>* modifiers) {
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
addModifier(*it);
}
}
// Add new modifier to attribute instance (takes ownership of modifier)
void ModifiableAttributeInstance::addModifier(AttributeModifier* modifier) {
// Can't add modifiers with the same ID (unless the modifier is anonymous)
if (modifier->getId() != eModifierId_ANONYMOUS &&
getModifier(modifier->getId()) != NULL) {
assert(0);
// throw new IllegalArgumentException("Modifier is already applied on
// this attribute!");
return;
}
modifiers[modifier->getOperation()].insert(modifier);
modifierById[modifier->getId()] = modifier;
setDirty();
}
void ModifiableAttributeInstance::setDirty() {
dirty = true;
attributeMap->onAttributeModified(this);
}
void ModifiableAttributeInstance::removeModifier(AttributeModifier* modifier) {
for (int i = 0; i < AttributeModifier::TOTAL_OPERATIONS; i++) {
for (AUTO_VAR(it, modifiers[i].begin()); it != modifiers[i].end();
++it) {
if (modifier->equals(*it)) {
modifiers[i].erase(it);
break;
}
}
}
modifierById.erase(modifier->getId());
setDirty();
}
void ModifiableAttributeInstance::removeModifier(eMODIFIER_ID id) {
AttributeModifier* modifier = getModifier(id);
if (modifier != NULL) removeModifier(modifier);
}
void ModifiableAttributeInstance::removeModifiers() {
std::unordered_set<AttributeModifier*> removingModifiers;
getModifiers(removingModifiers);
for (AUTO_VAR(it, removingModifiers.begin()); it != removingModifiers.end();
++it) {
removeModifier(*it);
}
}
double ModifiableAttributeInstance::getValue() {
if (dirty) {
cachedValue = calculateValue();
dirty = false;
}
return cachedValue;
}
double ModifiableAttributeInstance::calculateValue() {
double base = getBaseValue();
std::unordered_set<AttributeModifier*>* modifiers;
modifiers = getModifiers(AttributeModifier::OPERATION_ADDITION);
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
AttributeModifier* modifier = *it;
base += modifier->getAmount();
}
double result = base;
modifiers = getModifiers(AttributeModifier::OPERATION_MULTIPLY_BASE);
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
AttributeModifier* modifier = *it;
result += base * modifier->getAmount();
}
modifiers = getModifiers(AttributeModifier::OPERATION_MULTIPLY_TOTAL);
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
AttributeModifier* modifier = *it;
result *= 1 + modifier->getAmount();
}
return attribute->sanitizeValue(result);
}

View file

@ -0,0 +1,41 @@
#pragma once
#include "AttributeInstance.h"
class ModifiableAttributeInstance : public AttributeInstance {
private:
BaseAttributeMap* attributeMap;
Attribute* attribute;
std::unordered_set<AttributeModifier*>
modifiers[AttributeModifier::TOTAL_OPERATIONS];
std::unordered_map<unsigned int, AttributeModifier*> modifierById;
double baseValue;
bool dirty;
double cachedValue;
public:
ModifiableAttributeInstance(BaseAttributeMap* attributeMap,
Attribute* attribute);
~ModifiableAttributeInstance();
Attribute* getAttribute();
double getBaseValue();
void setBaseValue(double baseValue);
std::unordered_set<AttributeModifier*>* getModifiers(int operation);
void getModifiers(std::unordered_set<AttributeModifier*>& result);
AttributeModifier* getModifier(eMODIFIER_ID id);
void addModifiers(std::unordered_set<AttributeModifier*>* modifiers);
void addModifier(AttributeModifier* modifier);
private:
void setDirty();
public:
void removeModifier(AttributeModifier* modifier);
void removeModifier(eMODIFIER_ID id);
void removeModifiers();
double getValue();
private:
double calculateValue();
};

View file

@ -0,0 +1,28 @@
#include "../../Platform/stdafx.h"
#include "RangedAttribute.h"
RangedAttribute::RangedAttribute(eATTRIBUTE_ID id, double defaultValue,
double minValue, double maxValue)
: BaseAttribute(id, defaultValue) {
this->minValue = minValue;
this->maxValue = maxValue;
// if (minValue > maxValue) throw new IllegalArgumentException("Minimum
// value cannot be bigger than maximum value!"); if (defaultValue <
// minValue) throw new IllegalArgumentException("Default value cannot be
// lower than minimum value!"); if (defaultValue > maxValue) throw new
// IllegalArgumentException("Default value cannot be bigger than maximum
// value!");
}
double RangedAttribute::getMinValue() { return minValue; }
double RangedAttribute::getMaxValue() { return maxValue; }
double RangedAttribute::sanitizeValue(double value) {
if (value < minValue) value = minValue;
if (value > maxValue) value = maxValue;
return value;
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "BaseAttribute.h"
class RangedAttribute : public BaseAttribute {
private:
double minValue;
double maxValue;
public:
RangedAttribute(eATTRIBUTE_ID id, double defaultValue, double minValue,
double maxValue);
double getMinValue();
double getMaxValue();
double sanitizeValue(double value);
// 4J: Removed legacy name
// RangedAttribute *importLegacyName(const std::wstring &name);
// std::wstring getImportLegacyName();
};

View file

@ -0,0 +1,82 @@
#include "../../Platform/stdafx.h"
#include "Attribute.h"
#include "RangedAttribute.h"
#include "AttributeInstance.h"
#include "ModifiableAttributeInstance.h"
#include "ServersideAttributeMap.h"
AttributeInstance* ServersideAttributeMap::getInstance(Attribute* attribute) {
return BaseAttributeMap::getInstance(attribute);
}
AttributeInstance* ServersideAttributeMap::getInstance(eATTRIBUTE_ID id) {
AttributeInstance* result = BaseAttributeMap::getInstance(id);
// 4J: Removed legacy name
// If we didn't find it, search by legacy name
/*if (result == NULL)
{
AUTO_VAR(it, attributesByLegacy.find(name));
if(it != attributesByLegacy.end())
{
result = it->second;
}
}*/
return result;
}
AttributeInstance* ServersideAttributeMap::registerAttribute(
Attribute* attribute) {
AUTO_VAR(it, attributesById.find(attribute->getId()));
if (it != attributesById.end()) {
return it->second;
}
AttributeInstance* instance =
new ModifiableAttributeInstance(this, attribute);
attributesById.insert(std::pair<eATTRIBUTE_ID, AttributeInstance*>(
attribute->getId(), instance));
// 4J: Removed legacy name
// If this is a ranged attribute also add to legacy name map
/*RangedAttribute *rangedAttribute =
dynamic_cast<RangedAttribute*>(attribute); if (rangedAttribute != NULL &&
rangedAttribute->getImportLegacyName() != L"")
{
attributesByLegacy.insert(std::pair<std::wstring,
AttributeInstance*>(rangedAttribute->getImportLegacyName(), instance));
}*/
return instance;
}
void ServersideAttributeMap::onAttributeModified(
ModifiableAttributeInstance* attributeInstance) {
if (attributeInstance->getAttribute()->isClientSyncable()) {
dirtyAttributes.insert(attributeInstance);
}
}
std::unordered_set<AttributeInstance*>*
ServersideAttributeMap::getDirtyAttributes() {
return &dirtyAttributes;
}
std::unordered_set<AttributeInstance*>*
ServersideAttributeMap::getSyncableAttributes() {
std::unordered_set<AttributeInstance*>* result =
new std::unordered_set<AttributeInstance*>();
std::vector<AttributeInstance*> atts;
getAttributes(atts);
for (int i = 0; i < atts.size(); i++) {
AttributeInstance* instance = atts.at(i);
if (instance->getAttribute()->isClientSyncable()) {
result->insert(instance);
}
}
return result;
}

View file

@ -0,0 +1,24 @@
#pragma once
#include "BaseAttributeMap.h"
class ServersideAttributeMap : public BaseAttributeMap {
private:
std::unordered_set<AttributeInstance*> dirtyAttributes;
protected:
// 4J: Remove legacy name
// unordered_map<eATTRIBUTE_ID, AttributeInstance *> attributesByLegacy;
public:
// 4J-JEV: Changed from ModifiableAttributeInstance to AttributeInstance as
// they are not 'covariant' on PS4.
virtual AttributeInstance* getInstance(Attribute* attribute);
virtual AttributeInstance* getInstance(eATTRIBUTE_ID id);
virtual AttributeInstance* registerAttribute(Attribute* attribute);
virtual void onAttributeModified(
ModifiableAttributeInstance* attributeInstance);
virtual std::unordered_set<AttributeInstance*>* getDirtyAttributes();
virtual std::unordered_set<AttributeInstance*>* getSyncableAttributes();
};

View file

@ -5,7 +5,7 @@
const float BodyControl::maxClampAngle = 75.0f;
BodyControl::BodyControl(Mob* mob) {
BodyControl::BodyControl(LivingEntity* mob) {
this->mob = mob;
timeStill = 0;

View file

@ -4,13 +4,13 @@
class BodyControl : public Control {
private:
Mob* mob;
LivingEntity* mob;
static const float maxClampAngle;
int timeStill;
float lastHeadY;
public:
BodyControl(Mob* mob);
BodyControl(LivingEntity* mob);
void clientTick();

View file

@ -14,13 +14,14 @@ LookControl::LookControl(Mob* mob) {
void LookControl::setLookAt(std::shared_ptr<Entity> target, float yMax,
float xMax) {
this->wantedX = target->x;
std::shared_ptr<Mob> targetMob = std::dynamic_pointer_cast<Mob>(target);
if (targetMob != NULL)
this->wantedY = target->y + targetMob->getHeadHeight();
wantedX = target->x;
if (target->instanceof(eTYPE_LIVINGENTITY))
wantedY =
target->y +
std::dynamic_pointer_cast<LivingEntity>(target)->getHeadHeight();
else
this->wantedY = (target->bb->y0 + target->bb->y1) / 2;
this->wantedZ = target->z;
wantedY = (target->bb->y0 + target->bb->y1) / 2;
wantedZ = target->z;
this->yMax = yMax;
this->xMax = xMax;
hasWanted = true;
@ -28,9 +29,9 @@ void LookControl::setLookAt(std::shared_ptr<Entity> target, float yMax,
void LookControl::setLookAt(double x, double y, double z, float yMax,
float xMax) {
this->wantedX = x;
this->wantedY = y;
this->wantedZ = z;
wantedX = x;
wantedY = y;
wantedZ = z;
this->yMax = yMax;
this->xMax = xMax;
hasWanted = true;

View file

@ -1,6 +1,8 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.monster.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "MoveControl.h"
@ -13,20 +15,21 @@ MoveControl::MoveControl(Mob* mob) {
wantedY = mob->y;
wantedZ = mob->z;
speed = 0.0f;
speedModifier = 0.0;
_hasWanted = false;
}
bool MoveControl::hasWanted() { return _hasWanted; }
float MoveControl::getSpeed() { return speed; }
double MoveControl::getSpeedModifier() { return speedModifier; }
void MoveControl::setWantedPosition(double x, double y, double z, float speed) {
void MoveControl::setWantedPosition(double x, double y, double z,
double speedModifier) {
wantedX = x;
wantedY = y;
wantedZ = z;
this->speed = speed;
this->speedModifier = speedModifier;
_hasWanted = true;
}
@ -46,7 +49,10 @@ void MoveControl::tick() {
float yRotD = (float)(atan2(zd, xd) * 180 / PI) - 90;
mob->yRot = rotlerp(mob->yRot, yRotD, MAX_TURN);
mob->setSpeed(speed * mob->getWalkingSpeedModifier());
mob->setSpeed(
(float)(speedModifier *
mob->getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)
->getValue()));
if (yd > 0 && xd * xd + zd * zd < 1) mob->getJumpControl()->jump();
}

View file

@ -16,19 +16,18 @@ private:
double wantedX;
double wantedY;
double wantedZ;
float speed;
double speedModifier;
bool _hasWanted;
public:
MoveControl(Mob* mob);
virtual ~MoveControl() {}
bool hasWanted();
float getSpeed();
void setWantedPosition(double x, double y, double z, float speed);
double getSpeedModifier();
void setWantedPosition(double x, double y, double z, double speedModifier);
void setSpeed(float speed);
virtual void tick();
private:
float rotlerp(float a, float b, float max);
};
};

View file

@ -1,90 +0,0 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
#include "../../Headers/net.minecraft.world.entity.projectile.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "../../Util/SoundTypes.h"
#include "ArrowAttackGoal.h"
ArrowAttackGoal::ArrowAttackGoal(Mob* mob, float speed, int projectileType,
int attackInterval) {
// 4J Init
target = std::weak_ptr<Mob>();
attackTime = 0;
seeTime = 0;
this->mob = mob;
this->level = mob->level;
this->speed = speed;
this->projectileType = projectileType;
this->attackInterval = attackInterval;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag);
}
bool ArrowAttackGoal::canUse() {
std::shared_ptr<Mob> bestTarget = mob->getTarget();
if (bestTarget == NULL) return false;
target = std::weak_ptr<Mob>(bestTarget);
return true;
}
bool ArrowAttackGoal::canContinueToUse() {
return target.lock() != NULL &&
(canUse() || !mob->getNavigation()->isDone());
}
void ArrowAttackGoal::stop() { target = std::weak_ptr<Mob>(); }
void ArrowAttackGoal::tick() {
double attackRadiusSqr = 10 * 10;
std::shared_ptr<Mob> tar = target.lock();
double targetDistSqr = mob->distanceToSqr(tar->x, tar->bb->y0, tar->z);
bool canSee = mob->getSensing()->canSee(tar);
if (canSee) {
++seeTime;
} else
seeTime = 0;
if (targetDistSqr > attackRadiusSqr || seeTime < 20)
mob->getNavigation()->moveTo(tar, speed);
else
mob->getNavigation()->stop();
mob->getLookControl()->setLookAt(tar, 30, 30);
attackTime = std::max(attackTime - 1, 0);
if (attackTime > 0) return;
if (targetDistSqr > attackRadiusSqr || !canSee) return;
fireAtTarget();
attackTime = attackInterval;
}
void ArrowAttackGoal::fireAtTarget() {
std::shared_ptr<Mob> tar = target.lock();
if (projectileType == ArrowType) {
std::shared_ptr<Arrow> arrow = std::shared_ptr<Arrow>(new Arrow(
level, std::dynamic_pointer_cast<Mob>(mob->shared_from_this()), tar,
1.60f, 12));
level->playSound(mob->shared_from_this(), eSoundType_RANDOM_BOW, 1.0f,
1 / (mob->getRandom()->nextFloat() * 0.4f + 0.8f));
level->addEntity(arrow);
} else if (projectileType == SnowballType) {
std::shared_ptr<Snowball> snowball = std::shared_ptr<Snowball>(
new Snowball(level, std::dynamic_pointer_cast<Mob>(
mob->shared_from_this())));
double xd = tar->x - mob->x;
double yd = (tar->y + tar->getHeadHeight() - 1.1f) - snowball->y;
double zd = tar->z - mob->z;
float yo = sqrt(xd * xd + zd * zd) * 0.2f;
snowball->shoot(xd, yd + yo, zd, 1.60f, 12);
level->playSound(mob->shared_from_this(), eSoundType_RANDOM_BOW, 1.0f,
1 / (mob->getRandom()->nextFloat() * 0.4f + 0.8f));
level->addEntity(snowball);
}
}

View file

@ -1,34 +0,0 @@
#pragma once
#include "Goal.h"
class ArrowAttackGoal : public Goal {
public:
static const int ArrowType = 1;
static const int SnowballType = 2;
Level* level;
Mob* mob; // Owner of this goal
std::weak_ptr<Mob> target;
int attackTime;
float speed;
int seeTime;
int projectileType;
int attackInterval;
ArrowAttackGoal(Mob* mob, float speed, int projectileType,
int attackInterval);
virtual bool canUse();
virtual bool canContinueToUse();
virtual void stop();
virtual void tick();
private:
void fireAtTarget();
public:
// 4J Added override to update ai elements when loading entity from
// schematics
virtual void setLevel(Level* level) { this->level = level; }
};

View file

@ -10,24 +10,38 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "AvoidPlayerGoal.h"
AvoidPlayerGoalEntitySelector::AvoidPlayerGoalEntitySelector(
AvoidPlayerGoal* parent) {
m_parent = parent;
}
bool AvoidPlayerGoalEntitySelector::matches(
std::shared_ptr<Entity> entity) const {
return entity->isAlive() && m_parent->mob->getSensing()->canSee(entity);
}
AvoidPlayerGoal::AvoidPlayerGoal(PathfinderMob* mob,
const std::type_info& avoidType, float maxDist,
float walkSpeed, float sprintSpeed)
double walkSpeedModifier,
double sprintSpeedModifier)
: avoidType(avoidType) {
this->mob = mob;
// this->avoidType = avoidType;
this->maxDist = maxDist;
this->walkSpeed = walkSpeed;
this->sprintSpeed = sprintSpeed;
this->walkSpeedModifier = walkSpeedModifier;
this->sprintSpeedModifier = sprintSpeedModifier;
this->pathNav = mob->getNavigation();
setRequiredControlFlags(Control::MoveControlFlag);
entitySelector = new AvoidPlayerGoalEntitySelector(this);
toAvoid = std::weak_ptr<Entity>();
path = NULL;
}
AvoidPlayerGoal::~AvoidPlayerGoal() {
if (path != NULL) delete path;
delete entitySelector;
}
bool AvoidPlayerGoal::canUse() {
@ -40,8 +54,8 @@ bool AvoidPlayerGoal::canUse() {
if (toAvoid.lock() == NULL) return false;
} else {
std::vector<std::shared_ptr<Entity> >* entities =
mob->level->getEntitiesOfClass(avoidType,
mob->bb->grow(maxDist, 3, maxDist));
mob->level->getEntitiesOfClass(
avoidType, mob->bb->grow(maxDist, 3, maxDist), entitySelector);
if (entities->empty()) {
delete entities;
return false;
@ -50,8 +64,6 @@ bool AvoidPlayerGoal::canUse() {
delete entities;
}
if (!mob->getSensing()->canSee(toAvoid.lock())) return false;
Vec3* pos = RandomPos::getPosAvoid(
std::dynamic_pointer_cast<PathfinderMob>(mob->shared_from_this()), 16,
7,
@ -72,7 +84,7 @@ bool AvoidPlayerGoal::canContinueToUse() {
}
void AvoidPlayerGoal::start() {
pathNav->moveTo(path, walkSpeed);
pathNav->moveTo(path, walkSpeedModifier);
path = NULL;
}
@ -80,7 +92,7 @@ void AvoidPlayerGoal::stop() { toAvoid = std::weak_ptr<Entity>(); }
void AvoidPlayerGoal::tick() {
if (mob->distanceToSqr(toAvoid.lock()) < 7 * 7)
mob->getNavigation()->setSpeed(sprintSpeed);
mob->getNavigation()->setSpeedModifier(sprintSpeedModifier);
else
mob->getNavigation()->setSpeed(walkSpeed);
mob->getNavigation()->setSpeedModifier(walkSpeedModifier);
}

View file

@ -1,24 +1,39 @@
#pragma once
#include "Goal.h"
#include "../../Entities/EntitySelector.h"
class PathNavigation;
class PathfinderMob;
class Path;
class AvoidPlayerGoal;
class AvoidPlayerGoalEntitySelector : public EntitySelector {
private:
AvoidPlayerGoal* m_parent;
public:
AvoidPlayerGoalEntitySelector(AvoidPlayerGoal* parent);
bool matches(std::shared_ptr<Entity> entity) const;
};
class AvoidPlayerGoal : public Goal {
friend class AvoidPlayerGoalEntitySelector;
private:
PathfinderMob* mob; // Owner of this goal
float walkSpeed, sprintSpeed;
double walkSpeedModifier, sprintSpeedModifier;
std::weak_ptr<Entity> toAvoid;
float maxDist;
Path* path;
PathNavigation* pathNav;
const std::type_info& avoidType;
EntitySelector* entitySelector;
public:
AvoidPlayerGoal(PathfinderMob* mob, const std::type_info& avoidType,
float maxDist, float walkSpeed, float sprintSpeed);
float maxDist, double walkSpeedModifier,
double sprintSpeedModifier);
~AvoidPlayerGoal();
virtual bool canUse();

View file

@ -13,6 +13,8 @@ BreakDoorGoal::BreakDoorGoal(Mob* mob) : DoorInteractGoal(mob) {
bool BreakDoorGoal::canUse() {
if (!DoorInteractGoal::canUse()) return false;
if (!mob->level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING))
return false;
return !doorTile->isOpen(mob->level, doorX, doorY, doorZ);
}
@ -50,7 +52,7 @@ void BreakDoorGoal::tick() {
if (breakTime == DOOR_BREAK_TIME) {
if (mob->level->difficulty == Difficulty::HARD) {
mob->level->setTile(doorX, doorY, doorZ, 0);
mob->level->removeTile(doorX, doorY, doorZ);
mob->level->levelEvent(LevelEvent::SOUND_ZOMBIE_DOOR_CRASH, doorX,
doorY, doorZ, 0);
mob->level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, doorX,

View file

@ -4,18 +4,19 @@
#include "../../Headers/net.minecraft.world.entity.animal.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "../../Util/BasicTypeContainers.h"
#include "BreedGoal.h"
#include "../../Entities/Mobs/ExperienceOrb.h"
#include "../../Stats/GenericStats.h"
BreedGoal::BreedGoal(Animal* animal, float speed) {
BreedGoal::BreedGoal(Animal* animal, double speedModifier) {
partner = std::weak_ptr<Animal>();
loveTime = 0;
this->animal = animal;
this->level = animal->level;
this->speed = speed;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag);
}
@ -39,24 +40,27 @@ void BreedGoal::stop() {
void BreedGoal::tick() {
animal->getLookControl()->setLookAt(partner.lock(), 10,
animal->getMaxHeadXRot());
animal->getNavigation()->moveTo(partner.lock(), speed);
animal->getNavigation()->moveTo(partner.lock(), speedModifier);
++loveTime;
if (loveTime == 20 * 3) breed();
if (loveTime >= 20 * 3 && animal->distanceToSqr(partner.lock()) < 3 * 3)
breed();
}
std::shared_ptr<Animal> BreedGoal::getFreePartner() {
float r = 8;
std::vector<std::shared_ptr<Entity> >* others =
level->getEntitiesOfClass(typeid(*animal), animal->bb->grow(r, r, r));
double dist = Double::MAX_VALUE;
std::shared_ptr<Animal> partner = nullptr;
for (AUTO_VAR(it, others->begin()); it != others->end(); ++it) {
std::shared_ptr<Animal> p = std::dynamic_pointer_cast<Animal>(*it);
if (animal->canMate(p)) {
delete others;
return p;
if (animal->canMate(p) && animal->distanceToSqr(p) < dist) {
partner = p;
dist = animal->distanceToSqr(p);
}
}
delete others;
return nullptr;
return partner;
}
void BreedGoal::breed() {
@ -93,7 +97,7 @@ void BreedGoal::breed() {
partner.lock()->setAge(5 * 60 * 20);
animal->resetLove();
partner.lock()->resetLove();
offspring->setAge(-20 * 60 * 20);
offspring->setAge(AgableMob::BABY_START_AGE);
offspring->moveTo(animal->x, animal->y, animal->z, 0, 0);
offspring->setDespawnProtected();
level->addEntity(offspring);

View file

@ -11,10 +11,10 @@ private:
Level* level;
std::weak_ptr<Animal> partner;
int loveTime;
float speed;
double speedModifier;
public:
BreedGoal(Animal* animal, float speed);
BreedGoal(Animal* animal, double speedModifier);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -36,9 +36,8 @@ void ControlledByPlayerGoal::stop() {
}
bool ControlledByPlayerGoal::canUse() {
std::shared_ptr<Player> player =
std::dynamic_pointer_cast<Player>(mob->rider.lock());
return mob->isAlive() && player &&
return mob->isAlive() && mob->rider.lock() != NULL &&
mob->rider.lock()->instanceof(eTYPE_PLAYER) &&
(boosting || mob->canBeControlledByRider());
}
@ -119,7 +118,7 @@ void ControlledByPlayerGoal::tick() {
std::shared_ptr<ItemInstance> carriedItem = player->getCarriedItem();
if (carriedItem != NULL && carriedItem->id == Item::carrotOnAStick_Id) {
carriedItem->hurt(1, player);
carriedItem->hurtAndBreak(1, player);
if (carriedItem->count == 0) {
std::shared_ptr<ItemInstance> replacement =
@ -135,6 +134,12 @@ void ControlledByPlayerGoal::tick() {
mob->travel(0, moveSpeed);
}
bool ControlledByPlayerGoal::isNoJumpTile(int tile) {
return Tile::tiles[tile] != NULL &&
(Tile::tiles[tile]->getRenderShape() == Tile::SHAPE_STAIRS ||
(dynamic_cast<HalfSlabTile*>(Tile::tiles[tile]) != NULL));
}
bool ControlledByPlayerGoal::isBoosting() { return boosting; }
void ControlledByPlayerGoal::boost() {

View file

@ -1,7 +1,7 @@
#pragma once
#include "Goal.h"
#include "../../Util/SharedConstants.h"
#include "../Minecraft.World/SharedConstants.h"
class Mob;
@ -26,7 +26,12 @@ public:
void stop();
bool canUse();
void tick();
private:
bool isNoJumpTile(int tile);
public:
bool isBoosting();
void boost();
bool canBoost();
};
};

View file

@ -4,7 +4,7 @@
#include "DefendVillageTargetGoal.h"
DefendVillageTargetGoal::DefendVillageTargetGoal(VillagerGolem* golem)
: TargetGoal(golem, 16, false, true) {
: TargetGoal(golem, false, true) {
this->golem = golem;
setRequiredControlFlags(TargetGoal::TargetFlag);
}
@ -12,9 +12,21 @@ DefendVillageTargetGoal::DefendVillageTargetGoal(VillagerGolem* golem)
bool DefendVillageTargetGoal::canUse() {
std::shared_ptr<Village> village = golem->getVillage();
if (village == NULL) return false;
potentialTarget = std::weak_ptr<Mob>(village->getClosestAggressor(
std::dynamic_pointer_cast<Mob>(golem->shared_from_this())));
return canAttack(potentialTarget.lock(), false);
potentialTarget = std::weak_ptr<LivingEntity>(village->getClosestAggressor(
std::dynamic_pointer_cast<LivingEntity>(golem->shared_from_this())));
std::shared_ptr<LivingEntity> potTarget = potentialTarget.lock();
if (!canAttack(potTarget, false)) {
// look for bad players
if (mob->getRandom()->nextInt(20) == 0) {
potentialTarget = village->getClosestBadStandingPlayer(
std::dynamic_pointer_cast<LivingEntity>(
golem->shared_from_this()));
return canAttack(potTarget, false);
}
return false;
} else {
return true;
}
}
void DefendVillageTargetGoal::start() {

View file

@ -7,7 +7,7 @@ class VillagerGolem;
class DefendVillageTargetGoal : public TargetGoal {
private:
VillagerGolem* golem; // Owner of this goal
std::weak_ptr<Mob> potentialTarget;
std::weak_ptr<LivingEntity> potentialTarget;
public:
DefendVillageTargetGoal(VillagerGolem* golem);

View file

@ -10,7 +10,7 @@ EatTileGoal::EatTileGoal(Mob* mob) {
eatAnimationTick = 0;
this->mob = mob;
this->level = mob->level;
level = mob->level;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag |
Control::JumpControlFlag);
@ -51,15 +51,13 @@ void EatTileGoal::tick() {
int zz = Mth::floor(mob->z);
if (level->getTile(xx, yy, zz) == Tile::tallgrass_Id) {
level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, xx, yy, zz,
Tile::tallgrass_Id +
(TallGrass::TALL_GRASS << Tile::TILE_NUM_SHIFT));
level->setTile(xx, yy, zz, 0);
level->destroyTile(xx, yy, zz, false);
mob->ate();
} else if (level->getTile(xx, yy - 1, zz) == Tile::grass_Id) {
level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, xx, yy - 1, zz,
Tile::grass_Id);
level->setTile(xx, yy - 1, zz, Tile::dirt_Id);
level->setTileAndData(xx, yy - 1, zz, Tile::dirt_Id, 0,
Tile::UPDATE_CLIENTS);
mob->ate();
}
}

View file

@ -6,9 +6,9 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "FleeSunGoal.h"
FleeSunGoal::FleeSunGoal(PathfinderMob* mob, float speed) {
FleeSunGoal::FleeSunGoal(PathfinderMob* mob, double speedModifier) {
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
this->level = mob->level;
setRequiredControlFlags(Control::MoveControlFlag);
}
@ -31,7 +31,7 @@ bool FleeSunGoal::canUse() {
bool FleeSunGoal::canContinueToUse() { return !mob->getNavigation()->isDone(); }
void FleeSunGoal::start() {
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
}
Vec3* FleeSunGoal::getHidePos() {

View file

@ -6,11 +6,11 @@ class FleeSunGoal : public Goal {
private:
PathfinderMob* mob; // Owner of this goal
double wantedX, wantedY, wantedZ;
float speed;
double speedModifier;
Level* level;
public:
FleeSunGoal(PathfinderMob* mob, float speed);
FleeSunGoal(PathfinderMob* mob, double speedModifier);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -7,16 +7,16 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "FollowOwnerGoal.h"
FollowOwnerGoal::FollowOwnerGoal(TamableAnimal* tamable, float speed,
FollowOwnerGoal::FollowOwnerGoal(TamableAnimal* tamable, double speedModifier,
float startDistance, float stopDistance) {
owner = std::weak_ptr<Mob>();
timeToRecalcPath = 0;
oldAvoidWater = false;
this->tamable = tamable;
this->level = tamable->level;
this->speed = speed;
this->navigation = tamable->getNavigation();
level = tamable->level;
this->speedModifier = speedModifier;
navigation = tamable->getNavigation();
this->startDistance = startDistance;
this->stopDistance = stopDistance;
setRequiredControlFlags(Control::MoveControlFlag |
@ -24,12 +24,13 @@ FollowOwnerGoal::FollowOwnerGoal(TamableAnimal* tamable, float speed,
}
bool FollowOwnerGoal::canUse() {
std::shared_ptr<Mob> owner = tamable->getOwner();
std::shared_ptr<LivingEntity> owner =
std::dynamic_pointer_cast<LivingEntity>(tamable->getOwner());
if (owner == NULL) return false;
if (tamable->isSitting()) return false;
if (tamable->distanceToSqr(owner) < startDistance * startDistance)
return false;
this->owner = std::weak_ptr<Mob>(owner);
this->owner = std::weak_ptr<LivingEntity>(owner);
return true;
}
@ -59,7 +60,8 @@ void FollowOwnerGoal::tick() {
if (--timeToRecalcPath > 0) return;
timeToRecalcPath = 10;
if (navigation->moveTo(owner.lock(), speed)) return;
if (navigation->moveTo(owner.lock(), speedModifier)) return;
if (tamable->isLeashed()) return;
if (tamable->distanceToSqr(owner.lock()) <
TeleportDistance * TeleportDistance)
return;

View file

@ -11,17 +11,17 @@ public:
private:
TamableAnimal* tamable; // Owner of this goal
std::weak_ptr<Mob> owner;
std::weak_ptr<LivingEntity> owner;
Level* level;
float speed;
double speedModifier;
PathNavigation* navigation;
int timeToRecalcPath;
float stopDistance, startDistance;
bool oldAvoidWater;
public:
FollowOwnerGoal(TamableAnimal* tamable, float speed, float startDistance,
float stopDistance);
FollowOwnerGoal(TamableAnimal* tamable, double speedModifier,
float startDistance, float stopDistance);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -6,11 +6,11 @@
#include "../../Util/BasicTypeContainers.h"
#include "FollowParentGoal.h"
FollowParentGoal::FollowParentGoal(Animal* animal, float speed) {
FollowParentGoal::FollowParentGoal(Animal* animal, double speedModifier) {
timeToRecalcPath = 0;
this->animal = animal;
this->speed = speed;
this->speedModifier = speedModifier;
}
bool FollowParentGoal::canUse() {
@ -52,5 +52,5 @@ void FollowParentGoal::stop() { parent = std::weak_ptr<Animal>(); }
void FollowParentGoal::tick() {
if (--timeToRecalcPath > 0) return;
timeToRecalcPath = 10;
animal->getNavigation()->moveTo(parent.lock(), speed);
animal->getNavigation()->moveTo(parent.lock(), speedModifier);
}

View file

@ -8,11 +8,11 @@ class FollowParentGoal : public Goal {
private:
Animal* animal; // Owner of this goal
std::weak_ptr<Animal> parent;
float speed;
double speedModifier;
int timeToRecalcPath;
public:
FollowParentGoal(Animal* animal, float speed);
FollowParentGoal(Animal* animal, double speedModifier);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -28,6 +28,27 @@ void GoalSelector::addGoal(
goals.push_back(new InternalGoal(prio, goal, canDeletePointer));
}
void GoalSelector::removeGoal(Goal* toRemove) {
for (AUTO_VAR(it, goals.begin()); it != goals.end();) {
InternalGoal* ig = *it;
Goal* goal = ig->goal;
if (goal == toRemove) {
AUTO_VAR(it2, find(usingGoals.begin(), usingGoals.end(), ig));
if (it2 != usingGoals.end()) {
goal->stop();
usingGoals.erase(it2);
}
if (ig->canDeletePointer) delete ig->goal;
delete ig;
it = goals.erase(it);
} else {
++it;
}
}
}
void GoalSelector::tick() {
std::vector<InternalGoal*> toStart;

View file

@ -26,6 +26,7 @@ public:
// 4J Added canDelete param
void addGoal(int prio, Goal* goal, bool canDeletePointer = true);
void removeGoal(Goal* toRemove);
void tick();
std::vector<InternalGoal*>* getRunningGoals();

View file

@ -4,41 +4,40 @@
#include "../../Headers/net.minecraft.world.level.h"
#include "HurtByTargetGoal.h"
HurtByTargetGoal::HurtByTargetGoal(Mob* mob, bool alertSameType)
: TargetGoal(mob, 16, false) {
HurtByTargetGoal::HurtByTargetGoal(PathfinderMob* mob, bool alertSameType)
: TargetGoal(mob, false) {
this->alertSameType = alertSameType;
setRequiredControlFlags(TargetGoal::TargetFlag);
timestamp = 0;
}
bool HurtByTargetGoal::canUse() {
return canAttack(mob->getLastHurtByMob(), false);
int ts = mob->getLastHurtByMobTimestamp();
return ts != timestamp && canAttack(mob->getLastHurtByMob(), false);
}
void HurtByTargetGoal::start() {
mob->setTarget(mob->getLastHurtByMob());
oldHurtByMob = mob->getLastHurtByMob();
timestamp = mob->getLastHurtByMobTimestamp();
if (alertSameType) {
double within = getFollowDistance();
std::vector<std::shared_ptr<Entity> >* nearby =
mob->level->getEntitiesOfClass(
typeid(*mob), AABB::newTemp(mob->x, mob->y, mob->z, mob->x + 1,
mob->y + 1, mob->z + 1)
->grow(within, 4, within));
for (AUTO_VAR(it, nearby->begin()); it != nearby->end(); ++it) {
std::shared_ptr<Mob> other = std::dynamic_pointer_cast<Mob>(*it);
std::shared_ptr<PathfinderMob> other =
std::dynamic_pointer_cast<PathfinderMob>(*it);
if (this->mob->shared_from_this() == other) continue;
if (other->getTarget() != NULL) continue;
if (other->isAlliedTo(mob->getLastHurtByMob()))
continue; // don't target allies
other->setTarget(mob->getLastHurtByMob());
}
delete nearby;
}
TargetGoal::start();
}
void HurtByTargetGoal::tick() {
if (mob->getLastHurtByMob() != NULL &&
mob->getLastHurtByMob() != oldHurtByMob) {
this->start();
}
}
}

View file

@ -5,12 +5,11 @@
class HurtByTargetGoal : public TargetGoal {
private:
bool alertSameType;
std::shared_ptr<Mob> oldHurtByMob;
int timestamp;
public:
HurtByTargetGoal(Mob* mob, bool alertSameType);
HurtByTargetGoal(PathfinderMob* mob, bool alertSameType);
bool canUse();
void start();
void tick();
};

View file

@ -4,7 +4,7 @@
#include "LeapAtTargetGoal.h"
LeapAtTargetGoal::LeapAtTargetGoal(Mob* mob, float yd) {
target = std::weak_ptr<Mob>();
target = std::weak_ptr<LivingEntity>();
this->mob = mob;
this->yd = yd;
@ -13,7 +13,7 @@ LeapAtTargetGoal::LeapAtTargetGoal(Mob* mob, float yd) {
}
bool LeapAtTargetGoal::canUse() {
target = std::weak_ptr<Mob>(mob->getTarget());
target = std::weak_ptr<LivingEntity>(mob->getTarget());
if (target.lock() == NULL) return false;
double d = mob->distanceToSqr(target.lock());
if (d < 2 * 2 || d > 4 * 4) return false;

View file

@ -5,7 +5,7 @@
class LeapAtTargetGoal : public Goal {
private:
Mob* mob; // Owner of this goal
std::weak_ptr<Mob> target;
std::weak_ptr<LivingEntity> target;
float yd;
public:

View file

@ -10,7 +10,7 @@ LookAtPlayerGoal::LookAtPlayerGoal(Mob* mob, const std::type_info& lookAtType,
: lookAtType(lookAtType) {
this->mob = mob;
this->lookDistance = lookDistance;
this->probability = 0.02f;
probability = 0.02f;
setRequiredControlFlags(Control::LookControlFlag);
lookTime = 0;
@ -29,13 +29,18 @@ LookAtPlayerGoal::LookAtPlayerGoal(Mob* mob, const std::type_info& lookAtType,
bool LookAtPlayerGoal::canUse() {
if (mob->getRandom()->nextFloat() >= probability) return false;
if (lookAtType == typeid(Player))
if (mob->getTarget() != NULL) {
lookAt = mob->getTarget();
}
if (lookAtType == typeid(Player)) {
lookAt =
mob->level->getNearestPlayer(mob->shared_from_this(), lookDistance);
else
} else {
lookAt = std::weak_ptr<Entity>(mob->level->getClosestEntityOfClass(
lookAtType, mob->bb->grow(lookDistance, 3, lookDistance),
mob->shared_from_this()));
}
return lookAt.lock() != NULL;
}

View file

@ -76,6 +76,10 @@ bool MakeLoveGoal::villageNeedsMoreVillagers() {
std::shared_ptr<Village> _village = village.lock();
if (_village == NULL) return false;
if (!_village->isBreedTimerOk()) {
return false;
}
int idealSize = (int)((float)_village->getDoorCount() * 0.35);
// System.out.println("idealSize: " + idealSize + " pop: " +
// village.getPopulationSize());
@ -90,11 +94,9 @@ void MakeLoveGoal::breed() {
villager->setAge(5 * 60 * 20);
// 4J - added limit to number of animals that can be bred
if (level->canCreateMore(eTYPE_VILLAGER, Level::eSpawnType_Breed)) {
std::shared_ptr<Villager> child =
std::shared_ptr<Villager>(new Villager(level));
std::shared_ptr<Villager> child = std::dynamic_pointer_cast<Villager>(
villager->getBreedOffspring(partner.lock()));
child->setAge(-20 * 60 * 20);
child->setProfession(
villager->getRandom()->nextInt(Villager::PROFESSION_MAX));
child->moveTo(villager->x, villager->y, villager->z, 0, 0);
level->addEntity(child);
level->broadcastEntityEvent(child, EntityEvent::LOVE_HEARTS);

View file

@ -7,13 +7,13 @@
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "MeleeAttackGoal.h"
#include "../Navigation/Path.h"
void MeleeAttackGoal::_init(Mob* mob, float speed, bool trackTarget) {
void MeleeAttackGoal::_init(PathfinderMob* mob, double speedModifier,
bool trackTarget) {
this->attackType = eTYPE_NOTSET;
this->mob = mob;
this->level = mob->level;
this->speed = speed;
level = mob->level;
this->speedModifier = speedModifier;
this->trackTarget = trackTarget;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag);
@ -23,14 +23,15 @@ void MeleeAttackGoal::_init(Mob* mob, float speed, bool trackTarget) {
timeToRecalcPath = 0;
}
MeleeAttackGoal::MeleeAttackGoal(Mob* mob, eINSTANCEOF attackType, float speed,
bool trackTarget) {
_init(mob, speed, trackTarget);
MeleeAttackGoal::MeleeAttackGoal(PathfinderMob* mob, eINSTANCEOF attackType,
double speedModifier, bool trackTarget) {
_init(mob, speedModifier, trackTarget);
this->attackType = attackType;
}
MeleeAttackGoal::MeleeAttackGoal(Mob* mob, float speed, bool trackTarget) {
_init(mob, speed, trackTarget);
MeleeAttackGoal::MeleeAttackGoal(PathfinderMob* mob, double speedModifier,
bool trackTarget) {
_init(mob, speedModifier, trackTarget);
}
MeleeAttackGoal::~MeleeAttackGoal() {
@ -38,57 +39,53 @@ MeleeAttackGoal::~MeleeAttackGoal() {
}
bool MeleeAttackGoal::canUse() {
std::shared_ptr<Mob> bestTarget = mob->getTarget();
if (bestTarget == NULL) return false;
if (!bestTarget->isAlive()) return false;
if (attackType != eTYPE_NOTSET &&
(attackType & bestTarget->GetType()) != attackType)
return false;
target = std::weak_ptr<Mob>(bestTarget);
std::shared_ptr<LivingEntity> target = mob->getTarget();
if (target == NULL) return false;
if (!target->isAlive()) return false;
if (attackType != NULL && !target->instanceof(attackType)) return false;
delete path;
path = mob->getNavigation()->createPath(target.lock());
path = mob->getNavigation()->createPath(target);
return path != NULL;
}
bool MeleeAttackGoal::canContinueToUse() {
std::shared_ptr<Mob> bestTarget = mob->getTarget();
if (bestTarget == NULL) return false;
if (target.lock() == NULL || !target.lock()->isAlive()) return false;
std::shared_ptr<LivingEntity> target = mob->getTarget();
if (target == NULL) return false;
if (!target->isAlive()) return false;
if (!trackTarget) return !mob->getNavigation()->isDone();
if (!mob->isWithinRestriction(Mth::floor(target.lock()->x),
Mth::floor(target.lock()->y),
Mth::floor(target.lock()->z)))
if (!mob->isWithinRestriction(Mth::floor(target->x), Mth::floor(target->y),
Mth::floor(target->z)))
return false;
return true;
}
void MeleeAttackGoal::start() {
mob->getNavigation()->moveTo(path, speed);
mob->getNavigation()->moveTo(path, speedModifier);
path = NULL;
timeToRecalcPath = 0;
}
void MeleeAttackGoal::stop() {
target = std::weak_ptr<Mob>();
mob->getNavigation()->stop();
}
void MeleeAttackGoal::stop() { mob->getNavigation()->stop(); }
void MeleeAttackGoal::tick() {
mob->getLookControl()->setLookAt(target.lock(), 30, 30);
if (trackTarget || mob->getSensing()->canSee(target.lock())) {
std::shared_ptr<LivingEntity> target = mob->getTarget();
mob->getLookControl()->setLookAt(target, 30, 30);
if (trackTarget || mob->getSensing()->canSee(target)) {
if (--timeToRecalcPath <= 0) {
timeToRecalcPath = 4 + mob->getRandom()->nextInt(7);
mob->getNavigation()->moveTo(target.lock(), speed);
mob->getNavigation()->moveTo(target, speedModifier);
}
}
attackTime = std::max(attackTime - 1, 0);
double meleeRadiusSqr = (mob->bbWidth * 2) * (mob->bbWidth * 2);
if (mob->distanceToSqr(target.lock()->x, target.lock()->bb->y0,
target.lock()->z) > meleeRadiusSqr)
double meleeRadiusSqr =
(mob->bbWidth * 2) * (mob->bbWidth * 2) + target->bbWidth;
if (mob->distanceToSqr(target->x, target->bb->y0, target->z) >
meleeRadiusSqr)
return;
if (attackTime > 0) return;
attackTime = 20;
mob->doHurtTarget(target.lock());
if (mob->getCarriedItem() != NULL) mob->swing();
mob->doHurtTarget(target);
}

View file

@ -3,28 +3,26 @@
#include "Goal.h"
class Level;
class Mob;
class PathfinderMob;
class Path;
class MeleeAttackGoal : public Goal {
private:
Level* level;
Mob* mob; // Owner of this goal
std::weak_ptr<Mob> target;
PathfinderMob* mob; // Owner of this goal
int attackTime;
float speed;
double speedModifier;
bool trackTarget;
Path* path;
eINSTANCEOF attackType;
int timeToRecalcPath;
void _init(Mob* mob, float speed, bool trackTarget);
void _init(PathfinderMob* mob, double speedModifier, bool trackTarget);
public:
MeleeAttackGoal(Mob* mob, eINSTANCEOF attackType, float speed,
bool trackTarget);
MeleeAttackGoal(Mob* mob, float speed, bool trackTarget);
MeleeAttackGoal(PathfinderMob* mob, eINSTANCEOF attackType,
double speedModifier, bool trackTarget);
MeleeAttackGoal(PathfinderMob* mob, double speedModifier, bool trackTarget);
~MeleeAttackGoal();
virtual bool canUse();

View file

@ -51,11 +51,11 @@ void MoveIndoorsGoal::start() {
_doorInfo->getIndoorY(),
_doorInfo->getIndoorZ() + 0.5));
if (pos != NULL)
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, 0.3f);
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, 1.0f);
} else
mob->getNavigation()->moveTo(_doorInfo->getIndoorX() + 0.5,
_doorInfo->getIndoorY(),
_doorInfo->getIndoorZ() + 0.5, 0.3f);
_doorInfo->getIndoorZ() + 0.5, 1.0f);
}
void MoveIndoorsGoal::stop() {

View file

@ -9,13 +9,14 @@
#include "MoveThroughVillageGoal.h"
#include "../Navigation/Path.h"
MoveThroughVillageGoal::MoveThroughVillageGoal(PathfinderMob* mob, float speed,
MoveThroughVillageGoal::MoveThroughVillageGoal(PathfinderMob* mob,
double speedModifier,
bool onlyAtNight) {
path = NULL;
doorInfo = std::weak_ptr<DoorInfo>();
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
this->onlyAtNight = onlyAtNight;
setRequiredControlFlags(Control::MoveControlFlag);
}
@ -68,7 +69,7 @@ bool MoveThroughVillageGoal::canContinueToUse() {
}
void MoveThroughVillageGoal::start() {
mob->getNavigation()->moveTo(path, speed);
mob->getNavigation()->moveTo(path, speedModifier);
path = NULL;
}

View file

@ -9,14 +9,15 @@ class DoorInfo;
class MoveThroughVillageGoal : public Goal {
private:
PathfinderMob* mob;
float speed;
double speedModifier;
Path* path;
std::weak_ptr<DoorInfo> doorInfo;
bool onlyAtNight;
std::vector<std::weak_ptr<DoorInfo> > visited;
public:
MoveThroughVillageGoal(PathfinderMob* mob, float speed, bool onlyAtNight);
MoveThroughVillageGoal(PathfinderMob* mob, double speedModifier,
bool onlyAtNight);
~MoveThroughVillageGoal();
virtual bool canUse();

View file

@ -7,11 +7,11 @@
#include "MoveTowardsRestrictionGoal.h"
MoveTowardsRestrictionGoal::MoveTowardsRestrictionGoal(PathfinderMob* mob,
float speed) {
double speedModifier) {
wantedX = wantedY = wantedZ = 0.0;
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag);
}
@ -33,5 +33,5 @@ bool MoveTowardsRestrictionGoal::canContinueToUse() {
}
void MoveTowardsRestrictionGoal::start() {
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
}

View file

@ -6,10 +6,10 @@ class MoveTowardsRestrictionGoal : public Goal {
private:
PathfinderMob* mob;
double wantedX, wantedY, wantedZ;
float speed;
double speedModifier;
public:
MoveTowardsRestrictionGoal(PathfinderMob* mob, float speed);
MoveTowardsRestrictionGoal(PathfinderMob* mob, double speedModifier);
bool canUse();
bool canContinueToUse();

View file

@ -6,16 +6,17 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "MoveTowardsTargetGoal.h"
MoveTowardsTargetGoal::MoveTowardsTargetGoal(PathfinderMob* mob, float speed,
MoveTowardsTargetGoal::MoveTowardsTargetGoal(PathfinderMob* mob,
double speedModifier,
float within) {
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
this->within = within;
setRequiredControlFlags(Control::MoveControlFlag);
}
bool MoveTowardsTargetGoal::canUse() {
target = std::weak_ptr<Mob>(mob->getTarget());
target = std::weak_ptr<LivingEntity>(mob->getTarget());
if (target.lock() == NULL) return false;
if (target.lock()->distanceToSqr(mob->shared_from_this()) > within * within)
return false;
@ -39,5 +40,5 @@ bool MoveTowardsTargetGoal::canContinueToUse() {
void MoveTowardsTargetGoal::stop() { target = std::weak_ptr<Mob>(); }
void MoveTowardsTargetGoal::start() {
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
}

View file

@ -5,12 +5,14 @@
class MoveTowardsTargetGoal : public Goal {
private:
PathfinderMob* mob;
std::weak_ptr<Mob> target;
std::weak_ptr<LivingEntity> target;
double wantedX, wantedY, wantedZ;
float speed, within;
double speedModifier;
float within;
public:
MoveTowardsTargetGoal(PathfinderMob* mob, float speed, float within);
MoveTowardsTargetGoal(PathfinderMob* mob, double speedModifier,
float within);
bool canUse();
bool canContinueToUse();

View file

@ -4,6 +4,21 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "NearestAttackableTargetGoal.h"
SubselectEntitySelector::SubselectEntitySelector(
NearestAttackableTargetGoal* parent, EntitySelector* subselector) {
m_parent = parent;
m_subselector = subselector;
}
SubselectEntitySelector::~SubselectEntitySelector() { delete m_subselector; }
bool SubselectEntitySelector::matches(std::shared_ptr<Entity> entity) const {
if (!entity->instanceof(eTYPE_LIVINGENTITY)) return false;
if (m_subselector != NULL && !m_subselector->matches(entity)) return false;
return m_parent->canAttack(std::dynamic_pointer_cast<LivingEntity>(entity),
false);
}
NearestAttackableTargetGoal::DistComp::DistComp(Entity* source) {
this->source = source;
}
@ -19,46 +34,41 @@ bool NearestAttackableTargetGoal::DistComp::operator()(
}
NearestAttackableTargetGoal::NearestAttackableTargetGoal(
Mob* mob, const std::type_info& targetType, float within,
int randomInterval, bool mustSee, bool mustReach /*= false*/)
: TargetGoal(mob, within, mustSee, mustReach), targetType(targetType) {
// this->targetType = targetType;
this->within = within;
PathfinderMob* mob, const std::type_info& targetType, int randomInterval,
bool mustSee, bool mustReach /*= false*/,
EntitySelector* entitySelector /* =NULL */)
: TargetGoal(mob, mustSee, mustReach), targetType(targetType) {
this->randomInterval = randomInterval;
this->distComp = new DistComp(mob);
setRequiredControlFlags(TargetGoal::TargetFlag);
this->selector = new SubselectEntitySelector(this, entitySelector);
}
NearestAttackableTargetGoal::~NearestAttackableTargetGoal() { delete distComp; }
NearestAttackableTargetGoal::~NearestAttackableTargetGoal() {
delete distComp;
delete selector;
}
bool NearestAttackableTargetGoal::canUse() {
if (randomInterval > 0 && mob->getRandom()->nextInt(randomInterval) != 0)
return false;
if (targetType == typeid(Player)) {
std::shared_ptr<Mob> potentialTarget =
mob->level->getNearestAttackablePlayer(mob->shared_from_this(),
within);
if (canAttack(potentialTarget, false)) {
target = std::weak_ptr<Mob>(potentialTarget);
return true;
}
} else {
std::vector<std::shared_ptr<Entity> >* entities =
mob->level->getEntitiesOfClass(targetType,
mob->bb->grow(within, 4, within));
// Collections.sort(entities, distComp);
double within = getFollowDistance();
std::vector<std::shared_ptr<Entity> >* entities =
mob->level->getEntitiesOfClass(
targetType, mob->bb->grow(within, 4, within), selector);
bool result = false;
if (entities != NULL && !entities->empty()) {
std::sort(entities->begin(), entities->end(), *distComp);
for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) {
std::shared_ptr<Mob> potTarget =
std::dynamic_pointer_cast<Mob>(*it);
if (canAttack(potTarget, false)) {
target = std::weak_ptr<Mob>(potTarget);
return true;
}
}
delete entities;
target = std::weak_ptr<LivingEntity>(
std::dynamic_pointer_cast<LivingEntity>(entities->at(0)));
result = true;
}
return false;
delete entities;
return result;
}
void NearestAttackableTargetGoal::start() {

View file

@ -1,8 +1,26 @@
#pragma once
#include "TargetGoal.h"
#include "../../Entities/EntitySelector.h"
class NearestAttackableTargetGoal;
// Anonymous class from NearestAttackableTargetGoal
class SubselectEntitySelector : public EntitySelector {
private:
EntitySelector* m_subselector;
NearestAttackableTargetGoal* m_parent;
public:
SubselectEntitySelector(NearestAttackableTargetGoal* parent,
EntitySelector* subselector);
~SubselectEntitySelector();
bool matches(std::shared_ptr<Entity> entity) const;
};
class NearestAttackableTargetGoal : public TargetGoal {
friend class SubselectEntitySelector;
public:
class DistComp {
private:
@ -15,21 +33,19 @@ public:
};
private:
std::weak_ptr<Mob> target;
const std::type_info& targetType;
int randomInterval;
DistComp* distComp;
EntitySelector* selector;
std::weak_ptr<LivingEntity> target;
public:
// public NearestAttackableTargetGoal(Mob mob, const std::type_info&
// targetType, float within, int randomInterval, bool mustSee)
//{
// this(mob, targetType, within, randomInterval, mustSee, false);
// }
NearestAttackableTargetGoal(PathfinderMob* mob,
const std::type_info& targetType,
int randomInterval, bool mustSee,
bool mustReach = false,
EntitySelector* entitySelector = NULL);
NearestAttackableTargetGoal(Mob* mob, const std::type_info& targetType,
float within, int randomInterval, bool mustSee,
bool mustReach = false);
virtual ~NearestAttackableTargetGoal();
virtual bool canUse();

View file

@ -3,14 +3,12 @@
#include "NonTameRandomTargetGoal.h"
NonTameRandomTargetGoal::NonTameRandomTargetGoal(
TamableAnimal* mob, const std::type_info& targetType, float within,
int randomInterval, bool mustSee)
: NearestAttackableTargetGoal(mob, targetType, within, randomInterval,
mustSee) {
this->tamableMob = mob;
TamableAnimal* mob, const std::type_info& targetType, int randomInterval,
bool mustSee)
: NearestAttackableTargetGoal(mob, targetType, randomInterval, mustSee) {
tamableMob = mob;
}
bool NonTameRandomTargetGoal::canUse() {
if (tamableMob->isTame()) return false;
return NearestAttackableTargetGoal::canUse();
return !tamableMob->isTame() && NearestAttackableTargetGoal::canUse();
}

View file

@ -10,7 +10,7 @@ private:
public:
NonTameRandomTargetGoal(TamableAnimal* mob,
const std::type_info& targetType, float within,
const std::type_info& targetType,
int randomInterval, bool mustSee);
bool canUse();

View file

@ -6,8 +6,8 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "OcelotAttackGoal.h"
OzelotAttackGoal::OzelotAttackGoal(Mob* mob) {
target = std::weak_ptr<Mob>();
OcelotAttackGoal::OcelotAttackGoal(Mob* mob) {
target = std::weak_ptr<LivingEntity>();
attackTime = 0;
speed = 0;
trackTarget = false;
@ -18,38 +18,38 @@ OzelotAttackGoal::OzelotAttackGoal(Mob* mob) {
Control::LookControlFlag);
}
bool OzelotAttackGoal::canUse() {
std::shared_ptr<Mob> bestTarget = mob->getTarget();
bool OcelotAttackGoal::canUse() {
std::shared_ptr<LivingEntity> bestTarget = mob->getTarget();
if (bestTarget == NULL) return false;
target = std::weak_ptr<Mob>(bestTarget);
target = std::weak_ptr<LivingEntity>(bestTarget);
return true;
}
bool OzelotAttackGoal::canContinueToUse() {
bool OcelotAttackGoal::canContinueToUse() {
if (target.lock() == NULL || !target.lock()->isAlive()) return false;
if (mob->distanceToSqr(target.lock()) > 15 * 15) return false;
return !mob->getNavigation()->isDone() || canUse();
}
void OzelotAttackGoal::stop() {
void OcelotAttackGoal::stop() {
target = std::weak_ptr<Mob>();
mob->getNavigation()->stop();
}
void OzelotAttackGoal::tick() {
void OcelotAttackGoal::tick() {
mob->getLookControl()->setLookAt(target.lock(), 30, 30);
double meleeRadiusSqr = (mob->bbWidth * 2) * (mob->bbWidth * 2);
double distSqr = mob->distanceToSqr(target.lock()->x, target.lock()->bb->y0,
target.lock()->z);
float speed = Ozelot::WALK_SPEED;
double speedModifier = Ocelot::WALK_SPEED_MOD;
if (distSqr > meleeRadiusSqr && distSqr < 4 * 4)
speed = Ozelot::SPRINT_SPEED;
speedModifier = Ocelot::SPRINT_SPEED_MOD;
else if (distSqr < 15 * 15)
speed = Ozelot::SNEAK_SPEED;
speedModifier = Ocelot::SNEAK_SPEED_MOD;
mob->getNavigation()->moveTo(target.lock(), speed);
mob->getNavigation()->moveTo(target.lock(), speedModifier);
attackTime = std::max(attackTime - 1, 0);

View file

@ -2,17 +2,17 @@
#include "Goal.h"
class OzelotAttackGoal : public Goal {
class OcelotAttackGoal : public Goal {
private:
Level* level;
Mob* mob;
std::weak_ptr<Mob> target;
std::weak_ptr<LivingEntity> target;
int attackTime;
float speed;
bool trackTarget;
public:
OzelotAttackGoal(Mob* mob);
OcelotAttackGoal(Mob* mob);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -17,7 +17,7 @@ const int OcelotSitOnTileGoal::SIT_TICKS =
const int OcelotSitOnTileGoal::SEARCH_RANGE = 8;
const double OcelotSitOnTileGoal::SIT_CHANCE = 0.0065f;
OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ozelot* ocelot, float speed) {
OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ocelot* ocelot, double speedModifier) {
_tick = 0;
tryTicks = 0;
maxTicks = 0;
@ -26,7 +26,7 @@ OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ozelot* ocelot, float speed) {
tileZ = 0;
this->ocelot = ocelot;
this->speed = speed;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag |
Control::JumpControlFlag);
}
@ -43,16 +43,22 @@ bool OcelotSitOnTileGoal::canContinueToUse() {
void OcelotSitOnTileGoal::start() {
ocelot->getNavigation()->moveTo((float)tileX + 0.5, tileY + 1,
(float)tileZ + 0.5, speed);
(float)tileZ + 0.5, speedModifier);
_tick = 0;
tryTicks = 0;
maxTicks = ocelot->getRandom()->nextInt(
ocelot->getRandom()->nextInt(SIT_TICKS) + SIT_TICKS) +
SIT_TICKS;
ocelot->getSitGoal()->wantToSit(false);
ocelot->setSittingOnTile(true); // 4J-Added.
}
void OcelotSitOnTileGoal::stop() { ocelot->setSitting(false); }
void OcelotSitOnTileGoal::stop() {
ocelot->setSitting(false);
ocelot->setSittingOnTile(false); // 4J-Added.
}
void OcelotSitOnTileGoal::tick() {
_tick++;
@ -60,7 +66,7 @@ void OcelotSitOnTileGoal::tick() {
if (ocelot->distanceToSqr(tileX, tileY + 1, tileZ) > 1) {
ocelot->setSitting(false);
ocelot->getNavigation()->moveTo((float)tileX + 0.5, tileY + 1,
(float)tileZ + 0.5, speed);
(float)tileZ + 0.5, speedModifier);
tryTicks++;
} else if (!ocelot->isSitting()) {
ocelot->setSitting(true);
@ -82,9 +88,9 @@ bool OcelotSitOnTileGoal::findNearestTile() {
double dist = ocelot->distanceToSqr(x, y, z);
if (dist < distSqr) {
this->tileX = x;
this->tileY = y;
this->tileZ = z;
tileX = x;
tileY = y;
tileZ = z;
distSqr = dist;
}
}

View file

@ -2,7 +2,7 @@
#include "Goal.h"
class Ozelot;
class Ocelot;
class OcelotSitOnTileGoal : public Goal {
private:
@ -12,8 +12,8 @@ private:
static const double SIT_CHANCE;
private:
Ozelot* ocelot; // Owner of this goal
float speed;
Ocelot* ocelot; // Owner of this goal
double speedModifier;
int _tick;
int tryTicks;
int maxTicks;
@ -22,7 +22,7 @@ private:
int tileZ;
public:
OcelotSitOnTileGoal(Ozelot* ocelot, float speed);
OcelotSitOnTileGoal(Ocelot* ocelot, double speedModifier);
bool canUse();
bool canContinueToUse();

View file

@ -6,7 +6,7 @@
OpenDoorGoal::OpenDoorGoal(Mob* mob, bool closeDoorAfter)
: DoorInteractGoal(mob) {
this->mob = mob;
this->closeDoor = closeDoorAfter;
closeDoor = closeDoorAfter;
}
bool OpenDoorGoal::canContinueToUse() {

View file

@ -6,18 +6,31 @@
OwnerHurtByTargetGoal::OwnerHurtByTargetGoal(TamableAnimal* tameAnimal)
: TargetGoal(tameAnimal, 32, false) {
this->tameAnimal = tameAnimal;
timestamp = 0;
setRequiredControlFlags(TargetGoal::TargetFlag);
}
bool OwnerHurtByTargetGoal::canUse() {
if (!tameAnimal->isTame()) return false;
std::shared_ptr<Mob> owner = tameAnimal->getOwner();
std::shared_ptr<LivingEntity> owner =
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
if (owner == NULL) return false;
ownerLastHurtBy = std::weak_ptr<Mob>(owner->getLastHurtByMob());
return canAttack(ownerLastHurtBy.lock(), false);
ownerLastHurtBy = std::weak_ptr<LivingEntity>(owner->getLastHurtByMob());
int ts = owner->getLastHurtByMobTimestamp();
std::shared_ptr<LivingEntity> locked = ownerLastHurtBy.lock();
return ts != timestamp && canAttack(locked, false) &&
tameAnimal->wantsToAttack(locked, owner);
}
void OwnerHurtByTargetGoal::start() {
mob->setTarget(ownerLastHurtBy.lock());
std::shared_ptr<LivingEntity> owner =
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
if (owner != NULL) {
timestamp = owner->getLastHurtByMobTimestamp();
}
TargetGoal::start();
}

View file

@ -7,7 +7,8 @@ class TamableAnimal;
class OwnerHurtByTargetGoal : public TargetGoal {
private:
TamableAnimal* tameAnimal; // Owner of this goal
std::weak_ptr<Mob> ownerLastHurtBy;
std::weak_ptr<LivingEntity> ownerLastHurtBy;
int timestamp;
public:
OwnerHurtByTargetGoal(TamableAnimal* tameAnimal);

View file

@ -7,17 +7,29 @@ OwnerHurtTargetGoal::OwnerHurtTargetGoal(TamableAnimal* tameAnimal)
: TargetGoal(tameAnimal, 32, false) {
this->tameAnimal = tameAnimal;
setRequiredControlFlags(TargetGoal::TargetFlag);
timestamp = 0;
}
bool OwnerHurtTargetGoal::canUse() {
if (!tameAnimal->isTame()) return false;
std::shared_ptr<Mob> owner = tameAnimal->getOwner();
std::shared_ptr<LivingEntity> owner =
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
if (owner == NULL) return false;
ownerLastHurt = std::weak_ptr<Mob>(owner->getLastHurtMob());
return canAttack(ownerLastHurt.lock(), false);
ownerLastHurt = std::weak_ptr<LivingEntity>(owner->getLastHurtMob());
int ts = owner->getLastHurtMobTimestamp();
std::shared_ptr<LivingEntity> locked = ownerLastHurt.lock();
return ts != timestamp && canAttack(locked, false) &&
tameAnimal->wantsToAttack(locked, owner);
}
void OwnerHurtTargetGoal::start() {
mob->setTarget(ownerLastHurt.lock());
TargetGoal::start();
std::shared_ptr<LivingEntity> owner =
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
if (owner != NULL) {
timestamp = owner->getLastHurtMobTimestamp();
TargetGoal::start();
}
}

View file

@ -7,7 +7,8 @@ class TamableAnimal;
class OwnerHurtTargetGoal : public TargetGoal {
private:
TamableAnimal* tameAnimal; // Owner of this goal
std::weak_ptr<Mob> ownerLastHurt;
std::weak_ptr<LivingEntity> ownerLastHurt;
int timestamp;
public:
OwnerHurtTargetGoal(TamableAnimal* tameAnimal);

View file

@ -6,14 +6,14 @@
#include "../../Headers/net.minecraft.world.phys.h"
#include "PanicGoal.h"
PanicGoal::PanicGoal(PathfinderMob* mob, float speed) {
PanicGoal::PanicGoal(PathfinderMob* mob, double speedModifier) {
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag);
}
bool PanicGoal::canUse() {
if (mob->getLastHurtByMob() == NULL) return false;
if (mob->getLastHurtByMob() == NULL && !mob->isOnFire()) return false;
Vec3* pos = RandomPos::getPos(
std::dynamic_pointer_cast<PathfinderMob>(mob->shared_from_this()), 5,
4);
@ -25,7 +25,7 @@ bool PanicGoal::canUse() {
}
void PanicGoal::start() {
mob->getNavigation()->moveTo(posX, posY, posZ, speed);
mob->getNavigation()->moveTo(posX, posY, posZ, speedModifier);
}
bool PanicGoal::canContinueToUse() { return !mob->getNavigation()->isDone(); }

View file

@ -7,11 +7,11 @@ class PathfinderMob;
class PanicGoal : public Goal {
private:
PathfinderMob* mob;
float speed;
double speedModifier;
double posX, posY, posZ;
public:
PanicGoal(PathfinderMob* mob, float speed);
PanicGoal(PathfinderMob* mob, double speedModifier);
virtual bool canUse();
virtual void start();

View file

@ -9,13 +9,13 @@
#include "../../Util/BasicTypeContainers.h"
#include "PlayGoal.h"
PlayGoal::PlayGoal(Villager* mob, float speed) {
followFriend = std::weak_ptr<Mob>();
PlayGoal::PlayGoal(Villager* mob, double speedModifier) {
followFriend = std::weak_ptr<LivingEntity>();
wantedX = wantedY = wantedZ = 0.0;
playTime = 0;
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag);
}
@ -38,7 +38,7 @@ bool PlayGoal::canUse() {
double distSqr = friendV->distanceToSqr(mob->shared_from_this());
if (distSqr > closestDistSqr) continue;
closestDistSqr = distSqr;
followFriend = std::weak_ptr<Mob>(friendV);
followFriend = std::weak_ptr<LivingEntity>(friendV);
}
delete children;
@ -62,14 +62,14 @@ void PlayGoal::start() {
void PlayGoal::stop() {
mob->setChasing(false);
followFriend = std::weak_ptr<Mob>();
followFriend = std::weak_ptr<LivingEntity>();
}
void PlayGoal::tick() {
--playTime;
if (followFriend.lock() != NULL) {
if (mob->distanceToSqr(followFriend.lock()) > 2 * 2)
mob->getNavigation()->moveTo(followFriend.lock(), speed);
mob->getNavigation()->moveTo(followFriend.lock(), speedModifier);
} else {
if (mob->getNavigation()->isDone()) {
Vec3* pos =
@ -77,7 +77,7 @@ void PlayGoal::tick() {
mob->shared_from_this()),
16, 3);
if (pos == NULL) return;
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, speed);
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, speedModifier);
}
}
}

View file

@ -5,13 +5,13 @@
class PlayGoal : public Goal {
private:
Villager* mob;
std::weak_ptr<Mob> followFriend;
float speed;
std::weak_ptr<LivingEntity> followFriend;
double speedModifier;
double wantedX, wantedY, wantedZ;
int playTime;
public:
PlayGoal(Villager* mob, float speed);
PlayGoal(Villager* mob, double speedModifier);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -7,9 +7,9 @@
#include "../../Util/SharedConstants.h"
#include "RandomStrollGoal.h"
RandomStrollGoal::RandomStrollGoal(PathfinderMob* mob, float speed) {
RandomStrollGoal::RandomStrollGoal(PathfinderMob* mob, double speedModifier) {
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag);
}
@ -57,5 +57,5 @@ bool RandomStrollGoal::canContinueToUse() {
}
void RandomStrollGoal::start() {
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
}

View file

@ -8,10 +8,10 @@ class RandomStrollGoal : public Goal {
private:
PathfinderMob* mob;
double wantedX, wantedY, wantedZ;
float speed;
double speedModifier;
public:
RandomStrollGoal(PathfinderMob* mob, float speed);
RandomStrollGoal(PathfinderMob* mob, double speedModifier);
virtual bool canUse();
virtual bool canContinueToUse();

View file

@ -0,0 +1,103 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.monster.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "RangedAttackGoal.h"
void RangedAttackGoal::_init(RangedAttackMob* rangedMob, Mob* mob,
double speedModifier, int attackIntervalMin,
int attackIntervalMax, float attackRadius) {
// if (!(mob instanceof LivingEntity))
//{
// throw new IllegalArgumentException("ArrowAttackGoal requires Mob
// implements RangedAttackMob");
// }
rangedAttackMob = rangedMob;
this->mob = mob;
this->speedModifier = speedModifier;
this->attackIntervalMin = attackIntervalMin;
this->attackIntervalMax = attackIntervalMax;
this->attackRadius = attackRadius;
attackRadiusSqr = attackRadius * attackRadius;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag);
target = std::weak_ptr<LivingEntity>();
attackTime = -1;
seeTime = 0;
}
RangedAttackGoal::RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob,
double speedModifier, int attackInterval,
float attackRadius) {
_init(rangedMob, mob, speedModifier, attackInterval, attackInterval,
attackRadius);
}
RangedAttackGoal::RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob,
double speedModifier, int attackIntervalMin,
int attackIntervalMax, float attackRadius) {
_init(rangedMob, mob, speedModifier, attackIntervalMin, attackIntervalMax,
attackRadius);
}
bool RangedAttackGoal::canUse() {
std::shared_ptr<LivingEntity> bestTarget = mob->getTarget();
if (bestTarget == NULL) return false;
target = std::weak_ptr<LivingEntity>(bestTarget);
return true;
}
bool RangedAttackGoal::canContinueToUse() {
return canUse() || !mob->getNavigation()->isDone();
}
void RangedAttackGoal::stop() {
target = std::weak_ptr<LivingEntity>();
seeTime = 0;
attackTime = -1;
}
void RangedAttackGoal::tick() {
// 4J: It's possible the target has gone since canUse selected it, don't do
// tick if target is null
if (target.lock() == NULL) return;
double targetDistSqr = mob->distanceToSqr(
target.lock()->x, target.lock()->bb->y0, target.lock()->z);
bool canSee = mob->getSensing()->canSee(target.lock());
if (canSee) {
seeTime++;
} else {
seeTime = 0;
}
if (targetDistSqr > attackRadiusSqr || seeTime < 20) {
mob->getNavigation()->moveTo(target.lock(), speedModifier);
} else {
mob->getNavigation()->stop();
}
mob->getLookControl()->setLookAt(target.lock(), 30, 30);
if (--attackTime == 0) {
if (targetDistSqr > attackRadiusSqr || !canSee) return;
float dist = Mth::sqrt(targetDistSqr) / attackRadius;
float power = dist;
if (power < 0.1f) power = 0.1f;
if (power > 1) power = 1;
rangedAttackMob->performRangedAttack(target.lock(), power);
attackTime = Mth::floor(dist * (attackIntervalMax - attackIntervalMin) +
attackIntervalMin);
} else if (attackTime < 0) {
float dist = Mth::sqrt(targetDistSqr) / attackRadius;
attackTime = Mth::floor(dist * (attackIntervalMax - attackIntervalMin) +
attackIntervalMin);
}
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "Goal.h"
class RangedAttackMob;
class RangedAttackGoal : public Goal {
private:
Mob* mob; // Owner
RangedAttackMob* rangedAttackMob; // owner
std::weak_ptr<LivingEntity> target;
int attackTime;
double speedModifier;
int seeTime;
int attackIntervalMin;
int attackIntervalMax;
float attackRadius;
float attackRadiusSqr;
void _init(RangedAttackMob* rangedMob, Mob* mob, double speedModifier,
int attackIntervalMin, int attackIntervalMax,
float attackRadius);
public:
// 4J Added extra Mob param to avoid weird type conversion problems
RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob, double speedModifier,
int attackInterval, float attackRadius);
RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob, double speedModifier,
int attackIntervalMin, int attackIntervalMax,
float attackRadius);
bool canUse();
bool canContinueToUse();
void stop();
void tick();
};

View file

@ -0,0 +1,60 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.animal.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.player.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../Navigation/RandomPos.h"
#include "RunAroundLikeCrazyGoal.h"
RunAroundLikeCrazyGoal::RunAroundLikeCrazyGoal(EntityHorse* mob,
double speedModifier) {
horse = mob;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag);
}
bool RunAroundLikeCrazyGoal::canUse() {
if (horse->isTamed() || horse->rider.lock() == NULL) return false;
Vec3* pos = RandomPos::getPos(
std::dynamic_pointer_cast<PathfinderMob>(horse->shared_from_this()), 5,
4);
if (pos == NULL) return false;
posX = pos->x;
posY = pos->y;
posZ = pos->z;
return true;
}
void RunAroundLikeCrazyGoal::start() {
horse->getNavigation()->moveTo(posX, posY, posZ, speedModifier);
}
bool RunAroundLikeCrazyGoal::canContinueToUse() {
return !horse->getNavigation()->isDone() && horse->rider.lock() != NULL;
}
void RunAroundLikeCrazyGoal::tick() {
if (horse->getRandom()->nextInt(50) == 0) {
if (horse->rider.lock()->instanceof(eTYPE_PLAYER)) {
int temper = horse->getTemper();
int maxTemper = horse->getMaxTemper();
if (maxTemper > 0 &&
horse->getRandom()->nextInt(maxTemper) < temper) {
horse->tameWithName(
std::dynamic_pointer_cast<Player>(horse->rider.lock()));
horse->level->broadcastEntityEvent(
horse->shared_from_this(), EntityEvent::TAMING_SUCCEEDED);
return;
}
horse->modifyTemper(5);
}
horse->rider.lock()->ride(nullptr);
horse->rider = std::weak_ptr<LivingEntity>();
horse->makeMad();
horse->level->broadcastEntityEvent(horse->shared_from_this(),
EntityEvent::TAMING_FAILED);
}
}

View file

@ -0,0 +1,20 @@
#pragma once
#include "Goal.h"
class EntityHorse;
class RunAroundLikeCrazyGoal : public Goal {
private:
EntityHorse* horse; // Owner
double speedModifier;
double posX, posY, posZ;
public:
RunAroundLikeCrazyGoal(EntityHorse* mob, double speedModifier);
bool canUse();
void start();
bool canContinueToUse();
void tick();
};

View file

@ -19,7 +19,8 @@ bool SitGoal::canUse() {
if (mob->isInWater()) return false;
if (!mob->onGround) return false;
std::shared_ptr<Mob> owner = mob->getOwner();
std::shared_ptr<LivingEntity> owner =
std::dynamic_pointer_cast<LivingEntity>(mob->getOwner());
if (owner == NULL) return true; // owner not on level
if (mob->distanceToSqr(owner) < FollowOwnerGoal::TeleportDistance *

View file

@ -6,24 +6,24 @@
#include "SwellGoal.h"
SwellGoal::SwellGoal(Creeper* creeper) {
target = std::weak_ptr<Mob>();
target = std::weak_ptr<LivingEntity>();
this->creeper = creeper;
setRequiredControlFlags(Control::MoveControlFlag);
}
bool SwellGoal::canUse() {
std::shared_ptr<Mob> target = creeper->getTarget();
std::shared_ptr<LivingEntity> target = creeper->getTarget();
return creeper->getSwellDir() > 0 ||
(target != NULL && (creeper->distanceToSqr(target) < 3 * 3));
}
void SwellGoal::start() {
creeper->getNavigation()->stop();
target = std::weak_ptr<Mob>(creeper->getTarget());
target = std::weak_ptr<LivingEntity>(creeper->getTarget());
}
void SwellGoal::stop() { target = std::weak_ptr<Mob>(); }
void SwellGoal::stop() { target = std::weak_ptr<LivingEntity>(); }
void SwellGoal::tick() {
if (target.lock() == NULL) {

View file

@ -7,7 +7,7 @@ class Creeper;
class SwellGoal : public Goal {
private:
Creeper* creeper;
std::weak_ptr<Mob> target;
std::weak_ptr<LivingEntity> target;
public:
SwellGoal(Creeper* creeper);

View file

@ -62,7 +62,7 @@ void TakeFlowerGoal::stop() {
void TakeFlowerGoal::tick() {
villager->getLookControl()->setLookAt(golem.lock(), 30, 30);
if (golem.lock()->getOfferFlowerTick() == pickupTick) {
villager->getNavigation()->moveTo(golem.lock(), 0.15f);
villager->getNavigation()->moveTo(golem.lock(), 0.5f);
takeFlower = true;
}

View file

@ -1,36 +1,39 @@
#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.animal.h"
#include "../../Headers/net.minecraft.world.entity.monster.h"
#include "../../Headers/net.minecraft.world.entity.player.h"
#include "../../Headers/net.minecraft.world.level.pathfinder.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "TargetGoal.h"
void TargetGoal::_init(Mob* mob, float within, bool mustSee, bool mustReach) {
void TargetGoal::_init(PathfinderMob* mob, bool mustSee, bool mustReach) {
reachCache = EmptyReachCache;
reachCacheTime = 0;
unseenTicks = 0;
this->mob = mob;
this->within = within;
this->mustSee = mustSee;
this->mustReach = mustReach;
}
TargetGoal::TargetGoal(Mob* mob, float within, bool mustSee) {
_init(mob, within, mustSee, false);
TargetGoal::TargetGoal(PathfinderMob* mob, bool mustSee) {
_init(mob, mustSee, false);
}
TargetGoal::TargetGoal(Mob* mob, float within, bool mustSee, bool mustReach) {
_init(mob, within, mustSee, mustReach);
TargetGoal::TargetGoal(PathfinderMob* mob, bool mustSee, bool mustReach) {
_init(mob, mustSee, mustReach);
}
bool TargetGoal::canContinueToUse() {
std::shared_ptr<Mob> target = mob->getTarget();
std::shared_ptr<LivingEntity> target = mob->getTarget();
if (target == NULL) return false;
if (!target->isAlive()) return false;
double within = getFollowDistance();
if (mob->distanceToSqr(target) > within * within) return false;
if (mustSee) {
if (mob->getSensing()->canSee(target)) {
@ -42,6 +45,12 @@ bool TargetGoal::canContinueToUse() {
return true;
}
double TargetGoal::getFollowDistance() {
AttributeInstance* followRange =
mob->getAttribute(SharedMonsterAttributes::FOLLOW_RANGE);
return followRange == NULL ? 16 : followRange->getValue();
}
void TargetGoal::start() {
reachCache = EmptyReachCache;
reachCacheTime = 0;
@ -50,21 +59,28 @@ void TargetGoal::start() {
void TargetGoal::stop() { mob->setTarget(nullptr); }
bool TargetGoal::canAttack(std::shared_ptr<Mob> target,
bool TargetGoal::canAttack(std::shared_ptr<LivingEntity> target,
bool allowInvulnerable) {
if (target == NULL) return false;
if (target == mob->shared_from_this()) return false;
if (!target->isAlive()) return false;
if (!mob->canAttackType(target->GetType())) return false;
std::shared_ptr<TamableAnimal> tamableAnimal =
std::dynamic_pointer_cast<TamableAnimal>(mob->shared_from_this());
if (tamableAnimal != NULL && tamableAnimal->isTame()) {
std::shared_ptr<TamableAnimal> tamableTarget =
std::dynamic_pointer_cast<TamableAnimal>(target);
if (tamableTarget != NULL && tamableTarget->isTame()) return false;
if (target == tamableAnimal->getOwner()) return false;
} else if (std::dynamic_pointer_cast<Player>(target) != NULL) {
OwnableEntity* ownableMob = dynamic_cast<OwnableEntity*>(mob);
if (ownableMob != NULL && !ownableMob->getOwnerUUID().empty()) {
std::shared_ptr<OwnableEntity> ownableTarget =
std::dynamic_pointer_cast<OwnableEntity>(target);
if (ownableTarget != NULL && ownableMob->getOwnerUUID().compare(
ownableTarget->getOwnerUUID()) == 0) {
// We're attacking something owned by the same person...
return false;
}
if (target == ownableMob->getOwner()) {
// We're attacking our owner
return false;
}
} else if (target->instanceof(eTYPE_PLAYER)) {
if (!allowInvulnerable &&
(std::dynamic_pointer_cast<Player>(target))->abilities.invulnerable)
return false;
@ -86,7 +102,7 @@ bool TargetGoal::canAttack(std::shared_ptr<Mob> target,
return true;
}
bool TargetGoal::canReach(std::shared_ptr<Mob> target) {
bool TargetGoal::canReach(std::shared_ptr<LivingEntity> target) {
reachCacheTime = 10 + mob->getRandom()->nextInt(5);
Path* path = mob->getNavigation()->createPath(target);
if (path == NULL) return false;

View file

@ -2,6 +2,8 @@
#include "Goal.h"
class PathfinderMob;
class TargetGoal : public Goal {
public:
static const int TargetFlag = 1;
@ -13,8 +15,7 @@ private:
static const int UnseenMemoryTicks = 60;
protected:
Mob* mob; // Owner of this goal
float within;
PathfinderMob* mob; // Owner of this goal
bool mustSee;
private:
@ -23,20 +24,26 @@ private:
int reachCacheTime;
int unseenTicks;
void _init(Mob* mob, float within, bool mustSee, bool mustReach);
void _init(PathfinderMob* mob, bool mustSee, bool mustReach);
public:
TargetGoal(Mob* mob, float within, bool mustSee);
TargetGoal(Mob* mob, float within, bool mustSee, bool mustReach);
TargetGoal(PathfinderMob* mob, bool mustSee);
TargetGoal(PathfinderMob* mob, bool mustSee, bool mustReach);
virtual ~TargetGoal() {}
virtual bool canContinueToUse();
protected:
virtual double getFollowDistance();
public:
virtual void start();
virtual void stop();
protected:
virtual bool canAttack(std::shared_ptr<Mob> target, bool allowInvulnerable);
virtual bool canAttack(std::shared_ptr<LivingEntity> target,
bool allowInvulnerable);
private:
bool canReach(std::shared_ptr<Mob> target);
bool canReach(std::shared_ptr<LivingEntity> target);
};

View file

@ -6,7 +6,7 @@
#include "../../Headers/net.minecraft.world.level.h"
#include "TemptGoal.h"
TemptGoal::TemptGoal(PathfinderMob* mob, float speed, int itemId,
TemptGoal::TemptGoal(PathfinderMob* mob, double speedModifier, int itemId,
bool canScare) {
px = py = pz = pRotX = pRotY = 0.0;
player = std::weak_ptr<Player>();
@ -15,7 +15,7 @@ TemptGoal::TemptGoal(PathfinderMob* mob, float speed, int itemId,
oldAvoidWater = false;
this->mob = mob;
this->speed = speed;
this->speedModifier = speedModifier;
this->itemId = itemId;
this->canScare = canScare;
setRequiredControlFlags(Control::MoveControlFlag |
@ -81,7 +81,7 @@ void TemptGoal::tick() {
if (mob->distanceToSqr(player.lock()) < 2.5 * 2.5)
mob->getNavigation()->stop();
else
mob->getNavigation()->moveTo(player.lock(), speed);
mob->getNavigation()->moveTo(player.lock(), speedModifier);
}
bool TemptGoal::isRunning() { return _isRunning; }

View file

@ -5,7 +5,7 @@
class TemptGoal : public Goal {
private:
PathfinderMob* mob;
float speed;
double speedModifier;
double px, py, pz, pRotX, pRotY;
std::weak_ptr<Player> player;
int calmDown;
@ -15,7 +15,8 @@ private:
bool oldAvoidWater;
public:
TemptGoal(PathfinderMob* mob, float speed, int itemId, bool canScare);
TemptGoal(PathfinderMob* mob, double speedModifier, int itemId,
bool canScare);
bool canUse();
bool canContinueToUse();

View file

@ -168,7 +168,12 @@ Node* PathFinder::getNode(Entity* entity, int x, int y, int z, Node* size,
if (avoidWater && cost == TYPE_WATER) return NULL;
if (cost != TYPE_OPEN) break;
// fell too far?
if (++drop >= 4) return NULL;
if (++drop >= 4)
return NULL; // 4J - rolling this back to pre-java 1.6.4
// version as we're suspicious of the performance
// implications of this
// if (drop++ >=
// entity->getMaxFallDistance()) return NULL;
y--;
if (y > 0) best = getNode(x, y, z);
@ -221,6 +226,24 @@ int PathFinder::isFree(Entity* entity, int x, int y, int z, Node* size,
}
Tile* tile = Tile::tiles[tileId];
// 4J Stu - Use new getTileRenderShape passing in the tileId we
// have already got
if (entity->level->getTileRenderShape(tileId) ==
Tile::SHAPE_RAIL) {
int xt = Mth::floor(entity->x);
int yt = Mth::floor(entity->y);
int zt = Mth::floor(entity->z);
if (entity->level->getTileRenderShape(xt, yt, zt) ==
Tile::SHAPE_RAIL ||
entity->level->getTileRenderShape(xt, yt - 1, zt) ==
Tile::SHAPE_RAIL) {
continue;
} else {
return TYPE_FENCE;
}
}
if (tile->isPathfindable(entity->level, xx, yy, zz)) continue;
if (canOpenDoors && tileId == Tile::door_wood_Id) continue;

View file

@ -2,19 +2,21 @@
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.level.pathfinder.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.monster.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.level.tile.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "PathNavigation.h"
PathNavigation::PathNavigation(Mob* mob, Level* level, float maxDist) {
PathNavigation::PathNavigation(Mob* mob, Level* level) {
this->mob = mob;
this->level = level;
this->maxDist = maxDist;
dist = mob->getAttribute(SharedMonsterAttributes::FOLLOW_RANGE);
path = NULL;
speed = 0.0f;
speedModifier = 0.0;
avoidSun = false;
_tick = 0;
lastStuckCheck = 0;
@ -48,45 +50,51 @@ bool PathNavigation::canOpenDoors() { return _canOpenDoors; }
void PathNavigation::setAvoidSun(bool avoidSun) { this->avoidSun = avoidSun; }
void PathNavigation::setSpeed(float speed) { this->speed = speed; }
void PathNavigation::setSpeedModifier(double speedModifier) {
this->speedModifier = speedModifier;
}
void PathNavigation::setCanFloat(bool canFloat) { this->canFloat = canFloat; }
float PathNavigation::getMaxDist() { return (float)dist->getValue(); }
Path* PathNavigation::createPath(double x, double y, double z) {
if (!canUpdatePath()) return NULL;
return level->findPath(mob->shared_from_this(), Mth::floor(x), (int)y,
Mth::floor(z), maxDist, _canPassDoors, _canOpenDoors,
avoidWater, canFloat);
Mth::floor(z), getMaxDist(), _canPassDoors,
_canOpenDoors, avoidWater, canFloat);
}
bool PathNavigation::moveTo(double x, double y, double z, float speed) {
bool PathNavigation::moveTo(double x, double y, double z,
double speedModifier) {
MemSect(52);
Path* newPath = createPath(Mth::floor(x), (int)y, Mth::floor(z));
MemSect(0);
// No need to delete newPath here as this will be copied into the member
// variable path and the class can assume responsibility for it
return moveTo(newPath, speed);
return moveTo(newPath, speedModifier);
}
Path* PathNavigation::createPath(std::shared_ptr<Mob> target) {
Path* PathNavigation::createPath(std::shared_ptr<Entity> target) {
if (!canUpdatePath()) return NULL;
return level->findPath(mob->shared_from_this(), target, maxDist,
return level->findPath(mob->shared_from_this(), target, getMaxDist(),
_canPassDoors, _canOpenDoors, avoidWater, canFloat);
}
bool PathNavigation::moveTo(std::shared_ptr<Mob> target, float speed) {
bool PathNavigation::moveTo(std::shared_ptr<Entity> target,
double speedModifier) {
MemSect(53);
Path* newPath = createPath(target);
MemSect(0);
// No need to delete newPath here as this will be copied into the member
// variable path and the class can assume responsibility for it
if (newPath != NULL)
return moveTo(newPath, speed);
return moveTo(newPath, speedModifier);
else
return false;
}
bool PathNavigation::moveTo(Path* newPath, float speed) {
bool PathNavigation::moveTo(Path* newPath, double speedModifier) {
if (newPath == NULL) {
if (path != NULL) delete path;
path = NULL;
@ -101,7 +109,7 @@ bool PathNavigation::moveTo(Path* newPath, float speed) {
if (avoidSun) trimPathFromSun();
if (path->getSize() == 0) return false;
this->speed = speed;
this->speedModifier = speedModifier;
Vec3* mobPos = getTempMobPos();
lastStuckCheck = _tick;
lastStuckCheckPos->x = mobPos->x;
@ -123,7 +131,7 @@ void PathNavigation::tick() {
if (target == NULL) return;
mob->getMoveControl()->setWantedPosition(target->x, target->y, target->z,
speed);
speedModifier);
}
void PathNavigation::updatePath() {

View file

@ -9,8 +9,8 @@ private:
Mob* mob;
Level* level;
Path* path;
float speed;
float maxDist;
double speedModifier;
AttributeInstance* dist;
bool avoidSun;
int _tick;
int lastStuckCheck;
@ -22,7 +22,7 @@ private:
bool canFloat;
public:
PathNavigation(Mob* mob, Level* level, float maxDist);
PathNavigation(Mob* mob, Level* level);
~PathNavigation();
void setAvoidWater(bool avoidWater);
@ -32,13 +32,14 @@ public:
void setCanPassDoors(bool canPass);
bool canOpenDoors();
void setAvoidSun(bool avoidSun);
void setSpeed(float speed);
void setSpeedModifier(double speedModifier);
void setCanFloat(bool canFloat);
float getMaxDist();
Path* createPath(double x, double y, double z);
bool moveTo(double x, double y, double z, float speed);
Path* createPath(std::shared_ptr<Mob> target);
bool moveTo(std::shared_ptr<Mob> target, float speed);
bool moveTo(Path* newPath, float speed);
bool moveTo(double x, double y, double z, double speedModifier);
Path* createPath(std::shared_ptr<Entity> target);
bool moveTo(std::shared_ptr<Entity> target, double speedModifier);
bool moveTo(Path* newPath, double speedModifier);
Path* getPath();
void tick();