mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/4jcraft.git
synced 2026-06-21 14:55:32 +00:00
refactor: split java libs and nbt into separate projects
This commit is contained in:
42
minecraft/java/include/java/Arrays.h
Normal file
42
minecraft/java/include/java/Arrays.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class Arrays {
|
||||
public:
|
||||
static void fill(doubleArray arr, unsigned int from, unsigned int to,
|
||||
double value) {
|
||||
assert(from >= 0);
|
||||
assert(from <= to);
|
||||
assert(to <= arr.length);
|
||||
std::fill(arr.data + from, arr.data + to, value);
|
||||
}
|
||||
|
||||
static void fill(floatArray arr, unsigned int from, unsigned int to,
|
||||
float value) {
|
||||
assert(from >= 0);
|
||||
assert(from <= to);
|
||||
assert(to <= arr.length);
|
||||
std::fill(arr.data + from, arr.data + to, value);
|
||||
}
|
||||
|
||||
static void fill(BiomeArray arr, unsigned int from, unsigned int to,
|
||||
Biome* value) {
|
||||
assert(from >= 0);
|
||||
assert(from <= to);
|
||||
assert(to <= arr.length);
|
||||
std::fill(arr.data + from, arr.data + to, value);
|
||||
}
|
||||
|
||||
static void fill(byteArray arr, unsigned int from, unsigned int to,
|
||||
uint8_t value) {
|
||||
assert(from >= 0);
|
||||
assert(from <= to);
|
||||
assert(to <= arr.length);
|
||||
std::fill(arr.data + from, arr.data + to, value);
|
||||
}
|
||||
|
||||
static void fill(byteArray arr, uint8_t value) {
|
||||
std::fill(arr.data, arr.data + arr.length, value);
|
||||
}
|
||||
};
|
||||
36
minecraft/java/include/java/Buffer.h
Normal file
36
minecraft/java/include/java/Buffer.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
// A buffer is a linear, finite sequence of elements of a specific primitive
|
||||
// type. Aside from its content, the essential properties of a buffer are its
|
||||
// capacity, limit, and position:
|
||||
//
|
||||
// A buffer's capacity is the number of elements it contains. The capacity of a
|
||||
// buffer is never negative and never changes.
|
||||
//
|
||||
// A buffer's limit is the index of the first element that should not be read or
|
||||
// written. A buffer's limit is never negative and is never greater than its
|
||||
// capacity.
|
||||
//
|
||||
// A buffer's position is the index of the next element to be read or written.
|
||||
// A buffer's position is never negative and is never greater than its limit.
|
||||
class Buffer {
|
||||
protected:
|
||||
const unsigned int m_capacity;
|
||||
unsigned int m_position;
|
||||
unsigned int m_limit;
|
||||
unsigned int m_mark;
|
||||
bool hasBackingArray;
|
||||
|
||||
public:
|
||||
Buffer(unsigned int capacity);
|
||||
virtual ~Buffer() {}
|
||||
|
||||
Buffer* clear();
|
||||
Buffer* limit(unsigned int newLimit);
|
||||
unsigned int limit();
|
||||
Buffer* position(unsigned int newPosition);
|
||||
unsigned int position();
|
||||
unsigned int remaining();
|
||||
|
||||
virtual Buffer* flip() = 0;
|
||||
};
|
||||
46
minecraft/java/include/java/ByteBuffer.h
Normal file
46
minecraft/java/include/java/ByteBuffer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/Definitions.h" // 4jcraft TODO
|
||||
|
||||
class IntBuffer;
|
||||
class FloatBuffer;
|
||||
|
||||
class ByteBuffer : public Buffer {
|
||||
protected:
|
||||
uint8_t* buffer;
|
||||
ByteOrder byteOrder;
|
||||
|
||||
public:
|
||||
ByteBuffer(unsigned int capacity);
|
||||
static ByteBuffer* allocateDirect(int capacity);
|
||||
ByteBuffer(unsigned int capacity, uint8_t* backingArray);
|
||||
virtual ~ByteBuffer();
|
||||
|
||||
static ByteBuffer* wrap(byteArray& b);
|
||||
static ByteBuffer* allocate(unsigned int capacity);
|
||||
void order(ByteOrder a);
|
||||
ByteBuffer* flip();
|
||||
uint8_t* getBuffer();
|
||||
int getSize();
|
||||
int getInt();
|
||||
int getInt(unsigned int index);
|
||||
void get(byteArray) {} // 4J - TODO
|
||||
uint8_t get(int index);
|
||||
int64_t getLong();
|
||||
short getShort();
|
||||
void getShortArray(shortArray& s);
|
||||
ByteBuffer* put(int index, uint8_t b);
|
||||
ByteBuffer* putInt(int value);
|
||||
ByteBuffer* putInt(unsigned int index, int value);
|
||||
ByteBuffer* putShort(short value);
|
||||
ByteBuffer* putShortArray(shortArray& s);
|
||||
ByteBuffer* putLong(int64_t value);
|
||||
ByteBuffer* put(byteArray inputArray);
|
||||
byteArray array();
|
||||
IntBuffer* asIntBuffer();
|
||||
FloatBuffer* asFloatBuffer();
|
||||
};
|
||||
758
minecraft/java/include/java/Class.h
Normal file
758
minecraft/java/include/java/Class.h
Normal file
@@ -0,0 +1,758 @@
|
||||
#pragma once
|
||||
|
||||
class InputStream;
|
||||
|
||||
// This file aims to provide functionality to mimic the subset of java's Class
|
||||
// class that we require. Classes that require this functionality derive from
|
||||
// BaseObject, and each contain a unique nested class definition Class. There
|
||||
// are #defines here to simplify declaring classes with this added
|
||||
// functionality.
|
||||
|
||||
// 0b FFFF CCCC CCCC CCCC CCCC CCCC CCEE EEEE
|
||||
// |||| |||| |||| |||| |||| |||| |||| ||||
|
||||
// |||| |||| |||| |||| |||| |||| |||| |||\- BIT00: ENUM:
|
||||
// |||| |||| |||| |||| |||| |||| |||| ||\-- BIT01: ENUM:
|
||||
// |||| |||| |||| |||| |||| |||| |||| |\--- BIT02: ENUM:
|
||||
// |||| |||| |||| |||| |||| |||| |||| \---- BIT03: ENUM:
|
||||
// |||| |||| |||| |||| |||| |||| ||||
|
||||
// |||| |||| |||| |||| |||| |||| |||\------ BIT04: ENUM:
|
||||
// |||| |||| |||| |||| |||| |||| ||\------- BIT05: ENUM:
|
||||
// |||| |||| |||| |||| |||| |||| |\-------- BIT06: CLASS: WATER_MOB
|
||||
// |||| |||| |||| |||| |||| |||| \--------- BIT07: CLASS: AMBIENT_MOB
|
||||
// |||| |||| |||| |||| |||| ||||
|
||||
// |||| |||| |||| |||| |||| |||\----------- BIT08: CLASS: !ENTITY (so
|
||||
// we can hide TILE_ENTITY and DISPENSER_TILE_ENTITY bits which aren't
|
||||
// relevant for entities)
|
||||
// |||| |||| |||| |||| |||| ||\------------ BIT09: CLASS:
|
||||
// MINECART_CONTAINER
|
||||
// |||| |||| |||| |||| |||| |\------------- BIT10: CLASS: SLIME
|
||||
// |||| |||| |||| |||| |||| \-------------- BIT11: CLASS: ZOMBIE
|
||||
// |||| |||| |||| |||| ||||
|
||||
// |||| |||| |||| |||| |||\---------------- BIT12: CLASS: SPIDER
|
||||
// |||| |||| |||| |||| ||\----------------- BIT13: CLASS: COW
|
||||
// |||| |||| |||| |||| |\------------------ BIT14: CLASS: TAMABLE
|
||||
// |||| |||| |||| |||| \------------------- BIT15: CLASS: ANIMAL
|
||||
// |||| |||| |||| ||||
|
||||
// |||| |||| |||| |||\--------------------- BIT16: CLASS:
|
||||
// MONSTER
|
||||
// |||| |||| |||| ||\---------------------- BIT17: CLASS:
|
||||
// GOLEM
|
||||
// |||| |||| |||| |\----------------------- BIT18: CLASS: AGABLE_MOB
|
||||
// |||| |||| |||| \------------------------ BIT19: CLASS:
|
||||
// PATHFINDER_MOB
|
||||
// |||| |||| ||||
|
||||
// |||| |||| |||\-------------------------- BIT20: CLASS:
|
||||
// PLAYER
|
||||
// |||| |||| ||\--------------------------- BIT21: CLASS:
|
||||
// MOB
|
||||
// |||| |||| |\---------------------------- BIT22: CLASS:
|
||||
// HANGING_ENTITY
|
||||
// |||| |||| \----------------------------- BIT23: CLASS:
|
||||
// THROWABLE
|
||||
// |||| ||||
|
||||
// |||| |||\------------------------------- BIT24: CLASS: FIREBALL
|
||||
// |||| ||\-------------------------------- BIT25: CLASS: MINECART
|
||||
// |||| |\--------------------------------- BIT26: CLASS: LIVING_ENTITY
|
||||
// |||| \---------------------------------- BIT27: CLASS: ENTITY
|
||||
// ||||
|
||||
// |||\------------------------------------ BIT28: FLAGS: valid in
|
||||
// spawner flag
|
||||
// ||\------------------------------------- BIT29: FLAGS:
|
||||
// Spawnlimitcheck
|
||||
// |\-------------------------------------- BIT30: FLAGS: Enemy
|
||||
// \--------------------------------------- BIT31: FLAGS: projectile
|
||||
|
||||
#define Bit(a) ((1) << (a))
|
||||
|
||||
const unsigned int BIT_NOT_LIVING_ENTITY = Bit(25);
|
||||
|
||||
// Classes
|
||||
|
||||
const unsigned int BIT_FLYING_MOB = Bit(9);
|
||||
const unsigned int BIT_WATER_MOB = Bit(10);
|
||||
const unsigned int BIT_AMBIENT_MOB = Bit(11);
|
||||
|
||||
const unsigned int BIT_NOT_ENTITY = Bit(12);
|
||||
const unsigned int BIT_SLIME = Bit(13);
|
||||
const unsigned int BIT_ZOMBIE = Bit(14);
|
||||
const unsigned int BIT_SPIDER = Bit(15);
|
||||
|
||||
const unsigned int BIT_COW = Bit(16);
|
||||
const unsigned int BIT_TAMABLE = Bit(17);
|
||||
const unsigned int BIT_ANIMAL = Bit(18);
|
||||
const unsigned int BIT_MONSTER = Bit(19);
|
||||
const unsigned int BIT_MINECART_CONTAINER = Bit(19) | BIT_NOT_LIVING_ENTITY;
|
||||
|
||||
const unsigned int BIT_GOLEM = Bit(20);
|
||||
const unsigned int BIT_HANGING_ENTITY = Bit(20) | BIT_NOT_LIVING_ENTITY;
|
||||
const unsigned int BIT_AGABLE_MOB = Bit(21);
|
||||
const unsigned int BIT_THROWABLE = Bit(21) | BIT_NOT_LIVING_ENTITY;
|
||||
const unsigned int BIT_PATHFINDER_MOB = Bit(22);
|
||||
const unsigned int BIT_FIREBALL = Bit(22) | BIT_NOT_LIVING_ENTITY;
|
||||
const unsigned int BIT_PLAYER = Bit(23);
|
||||
const unsigned int BIT_MINECART = Bit(23) | BIT_NOT_LIVING_ENTITY;
|
||||
|
||||
const unsigned int BIT_MOB = Bit(24);
|
||||
const unsigned int BIT_GLOBAL_ENTITY = Bit(24) | BIT_NOT_LIVING_ENTITY;
|
||||
// const unsigned int BIT_NOT_LIVING_ENTITY
|
||||
// = Bit(25);
|
||||
const unsigned int BIT_LIVING_ENTITY = Bit(26);
|
||||
const unsigned int BIT_ENTITY = Bit(27);
|
||||
|
||||
// Flags
|
||||
const unsigned int BIT_VALID_IN_SPAWNER = Bit(28);
|
||||
const unsigned int BIT_ANIMALS_SPAWN_LIMIT_CHECK = Bit(29);
|
||||
const unsigned int BIT_ENEMY = Bit(30);
|
||||
const unsigned int BIT_PROJECTILE = Bit(31U);
|
||||
|
||||
// Tile Entities
|
||||
const unsigned int BIT_TILE_ENTITY = Bit(24) | BIT_NOT_ENTITY;
|
||||
const unsigned int BIT_DISPENSERTILEENTITY = Bit(25) | BIT_NOT_ENTITY;
|
||||
const unsigned int BIT_OTHER_NOT_ENTITIES = Bit(26) | BIT_NOT_ENTITY;
|
||||
|
||||
// 4J-JEV: These abstract classes only have one subclass, so ignore them.
|
||||
// const unsigned int BIT_WATER_MOB =
|
||||
// Bit(15); const unsigned int BIT_FLYING_MOB = Bit(17); const unsigned int
|
||||
// BIT_AMBIENT_MOB = Bit(18); const unsigned int
|
||||
// BIT_GLOBAL_ENTITY = Bit();
|
||||
|
||||
// #define ETYPE(a,b,c) ( (a) | (b) | (c) )
|
||||
|
||||
// 4J Stu - This Enum can be used as a more lightweight version of the above,
|
||||
// without having do dynamic casts 4J-PB - for replacement of instanceof
|
||||
enum eINSTANCEOF {
|
||||
eTYPE_NOTSET = 0,
|
||||
|
||||
// Flags.
|
||||
eTYPE_VALID_IN_SPAWNER_FLAG = BIT_VALID_IN_SPAWNER,
|
||||
eTYPE_ANIMALS_SPAWN_LIMIT_CHECK = BIT_ANIMALS_SPAWN_LIMIT_CHECK,
|
||||
eTYPE_ENEMY = BIT_ENEMY,
|
||||
eTYPE_PROJECTILE = BIT_PROJECTILE,
|
||||
|
||||
eTYPE_ENTITY = BIT_ENTITY,
|
||||
|
||||
eTYPE_LIVINGENTITY = eTYPE_ENTITY | BIT_LIVING_ENTITY,
|
||||
|
||||
eTYPE_MOB = eTYPE_LIVINGENTITY | BIT_MOB,
|
||||
|
||||
eTYPE_PATHFINDER_MOB = eTYPE_MOB | BIT_PATHFINDER_MOB,
|
||||
|
||||
eTYPE_AGABLE_MOB = eTYPE_PATHFINDER_MOB | BIT_AGABLE_MOB,
|
||||
|
||||
eTYPE_VILLAGER = eTYPE_AGABLE_MOB | 0x1, // 0x12000,
|
||||
|
||||
// 4J Stu - When adding new categories, please also update
|
||||
// ConsoleSchematicFile::generateSchematicFile so these can be saved out to
|
||||
// schematics
|
||||
eTYPE_ANIMAL = eTYPE_AGABLE_MOB | BIT_ANIMAL,
|
||||
|
||||
eTYPE_TAMABLE_ANIMAL = eTYPE_ANIMAL | BIT_TAMABLE,
|
||||
|
||||
eTYPE_OCELOT = eTYPE_TAMABLE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x1,
|
||||
eTYPE_WOLF = eTYPE_TAMABLE_ANIMAL | 0x2,
|
||||
|
||||
eTYPE_HORSE = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x1,
|
||||
eTYPE_SHEEP = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x2,
|
||||
eTYPE_PIG = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x3,
|
||||
eTYPE_CHICKEN = eTYPE_ANIMAL | 0x4,
|
||||
|
||||
eTYPE_COW = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | BIT_COW,
|
||||
eTYPE_MUSHROOMCOW = eTYPE_COW | 0x1,
|
||||
|
||||
eTYPE_WATERANIMAL = eTYPE_PATHFINDER_MOB | BIT_WATER_MOB, // 0x100,
|
||||
eTYPE_SQUID = eTYPE_WATERANIMAL | 0x1,
|
||||
|
||||
eTYPE_GOLEM = eTYPE_PATHFINDER_MOB | BIT_GOLEM,
|
||||
|
||||
eTYPE_SNOWMAN =
|
||||
eTYPE_GOLEM | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x1, // 0x4,
|
||||
eTYPE_VILLAGERGOLEM = eTYPE_GOLEM | 0x2, // 0x1000,
|
||||
|
||||
// 4J Stu - If you add new hostile mobs here you should also update the
|
||||
eTYPE_MONSTER = eTYPE_ENEMY | eTYPE_PATHFINDER_MOB | BIT_MONSTER,
|
||||
|
||||
eTYPE_SPIDER = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | BIT_SPIDER,
|
||||
eTYPE_CAVESPIDER = eTYPE_SPIDER | 0x1,
|
||||
|
||||
eTYPE_ZOMBIE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | BIT_ZOMBIE,
|
||||
eTYPE_PIGZOMBIE = eTYPE_ZOMBIE | 0x1,
|
||||
|
||||
eTYPE_CREEPER = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x1,
|
||||
eTYPE_GIANT = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x2,
|
||||
eTYPE_SKELETON = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x3,
|
||||
eTYPE_ENDERMAN = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x4,
|
||||
eTYPE_SILVERFISH = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x5,
|
||||
eTYPE_BLAZE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x6,
|
||||
eTYPE_WITCH = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x7,
|
||||
eTYPE_WITHERBOSS = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x8,
|
||||
|
||||
eTYPE_AMBIENT = eTYPE_MOB | BIT_AMBIENT_MOB,
|
||||
eTYPE_BAT = eTYPE_AMBIENT | eTYPE_VALID_IN_SPAWNER_FLAG | 0x1,
|
||||
|
||||
eTYPE_FLYING_MOB = eTYPE_MOB | BIT_FLYING_MOB,
|
||||
eTYPE_GHAST =
|
||||
eTYPE_FLYING_MOB | eTYPE_VALID_IN_SPAWNER_FLAG | eTYPE_ENEMY | 0x1,
|
||||
|
||||
eTYPE_SLIME =
|
||||
eTYPE_MOB | eTYPE_VALID_IN_SPAWNER_FLAG | eTYPE_ENEMY | BIT_SLIME,
|
||||
eTYPE_LAVASLIME = eTYPE_SLIME | 0x1,
|
||||
|
||||
eTYPE_ENDERDRAGON = eTYPE_MOB | 0x5,
|
||||
|
||||
eTYPE_PLAYER = eTYPE_LIVINGENTITY | BIT_PLAYER, // 0x8000,
|
||||
eTYPE_SERVERPLAYER = eTYPE_PLAYER | 0x1,
|
||||
eTYPE_REMOTEPLAYER = eTYPE_PLAYER | 0x2,
|
||||
eTYPE_LOCALPLAYER = eTYPE_PLAYER | 0x3,
|
||||
|
||||
eTYPE_GLOBAL_ENTITY = eTYPE_ENTITY | BIT_GLOBAL_ENTITY,
|
||||
eTYPE_LIGHTNINGBOLT = eTYPE_GLOBAL_ENTITY | 0x1,
|
||||
|
||||
eTYPE_MINECART = eTYPE_ENTITY | BIT_MINECART, // 0x200000,
|
||||
|
||||
eTYPE_MINECART_RIDEABLE = eTYPE_MINECART | 0x1,
|
||||
eTYPE_MINECART_SPAWNER = eTYPE_MINECART | 0x6,
|
||||
eTYPE_MINECART_FURNACE = eTYPE_MINECART | 0x3,
|
||||
eTYPE_MINECART_TNT = eTYPE_MINECART | 0x4,
|
||||
|
||||
eTYPE_MINECART_CONTAINER = eTYPE_MINECART | BIT_MINECART_CONTAINER,
|
||||
|
||||
eTYPE_MINECART_CHEST = eTYPE_MINECART_CONTAINER | 0x2,
|
||||
eTYPE_MINECART_HOPPER = eTYPE_MINECART_CONTAINER | 0x5,
|
||||
|
||||
eTYPE_FIREBALL = eTYPE_ENTITY | eTYPE_PROJECTILE | BIT_FIREBALL, // 0x2,
|
||||
|
||||
eTYPE_DRAGON_FIREBALL = eTYPE_FIREBALL | 0x1,
|
||||
eTYPE_WITHER_SKULL = eTYPE_FIREBALL | 0x2,
|
||||
eTYPE_LARGE_FIREBALL = eTYPE_FIREBALL | 0x3,
|
||||
eTYPE_SMALL_FIREBALL = eTYPE_FIREBALL | 0x4,
|
||||
|
||||
eTYPE_THROWABLE = eTYPE_ENTITY | eTYPE_PROJECTILE | BIT_THROWABLE,
|
||||
|
||||
eTYPE_SNOWBALL = eTYPE_THROWABLE | 0x1,
|
||||
eTYPE_THROWNEGG = eTYPE_THROWABLE | 0x2,
|
||||
eTYPE_THROWNENDERPEARL = eTYPE_THROWABLE | 0x3,
|
||||
eTYPE_THROWNPOTION = eTYPE_THROWABLE | 0x4,
|
||||
eTYPE_THROWNEXPBOTTLE = eTYPE_THROWABLE | 0x5,
|
||||
|
||||
eTYPE_HANGING_ENTITY = eTYPE_ENTITY | BIT_HANGING_ENTITY,
|
||||
|
||||
eTYPE_PAINTING = eTYPE_HANGING_ENTITY | 0x1,
|
||||
eTYPE_ITEM_FRAME = eTYPE_HANGING_ENTITY | 0x2,
|
||||
eTYPE_LEASHFENCEKNOT = eTYPE_HANGING_ENTITY | 0x3,
|
||||
|
||||
// Other Entities.
|
||||
|
||||
eTYPE_OTHER_ENTITIES = eTYPE_ENTITY + 1,
|
||||
|
||||
eTYPE_EXPERIENCEORB = (eTYPE_OTHER_ENTITIES + 2), // 1.8.2
|
||||
eTYPE_EYEOFENDERSIGNAL = (eTYPE_OTHER_ENTITIES + 3) | eTYPE_PROJECTILE,
|
||||
eTYPE_FIREWORKS_ROCKET = (eTYPE_OTHER_ENTITIES + 4) | eTYPE_PROJECTILE,
|
||||
eTYPE_FISHINGHOOK = (eTYPE_OTHER_ENTITIES + 5) | eTYPE_PROJECTILE,
|
||||
eTYPE_DELAYEDRELEASE = (eTYPE_OTHER_ENTITIES + 6), // 1.8.2
|
||||
eTYPE_BOAT = (eTYPE_OTHER_ENTITIES + 7),
|
||||
eTYPE_FALLINGTILE = (eTYPE_OTHER_ENTITIES + 8),
|
||||
eTYPE_ITEMENTITY = (eTYPE_OTHER_ENTITIES + 9),
|
||||
eTYPE_PRIMEDTNT = (eTYPE_OTHER_ENTITIES + 10),
|
||||
eTYPE_ARROW = (eTYPE_OTHER_ENTITIES + 11) | eTYPE_PROJECTILE,
|
||||
eTYPE_MULTIENTITY_MOB_PART = (eTYPE_OTHER_ENTITIES + 12),
|
||||
eTYPE_NETHER_SPHERE = (eTYPE_OTHER_ENTITIES + 13),
|
||||
eTYPE_ENDER_CRYSTAL = (eTYPE_OTHER_ENTITIES + 14),
|
||||
|
||||
// === PARTICLES === //
|
||||
|
||||
eType_BREAKINGITEMPARTICLE,
|
||||
eType_BUBBLEPARTICLE,
|
||||
eType_EXPLODEPARTICLE,
|
||||
eType_FLAMEPARTICLE,
|
||||
eType_FOOTSTEPPARTICLE,
|
||||
eType_HEARTPARTICLE,
|
||||
eType_LAVAPARTICLE,
|
||||
eType_NOTEPARTICLE,
|
||||
eType_NETHERPORTALPARTICLE,
|
||||
eType_REDDUSTPARTICLE,
|
||||
eType_SMOKEPARTICLE,
|
||||
eType_SNOWSHOVELPARTICLE,
|
||||
eType_SPLASHPARTICLE,
|
||||
eType_TAKEANIMATIONPARTICLE,
|
||||
eType_TERRAINPARTICLE,
|
||||
eType_WATERDROPPARTICLE,
|
||||
|
||||
// 1.8.2
|
||||
eType_CRITPARTICLE,
|
||||
eType_CRITPARTICLE2,
|
||||
eType_HUGEEXPLOSIONPARTICLE,
|
||||
eType_HUGEEXPLOSIONSEEDPARTICLE,
|
||||
eType_PLAYERCLOUDPARTICLEPARTICLE,
|
||||
eType_SUSPENDEDPARTICLE,
|
||||
eType_SUSPENDEDTOWNPARTICLE,
|
||||
|
||||
// 1.0.1
|
||||
eTYPE_DRIPPARTICLE,
|
||||
eTYPE_ENCHANTMENTTABLEPARTICLE,
|
||||
eTYPE_SPELLPARTICLE,
|
||||
|
||||
// TU9
|
||||
eTYPE_DRAGONBREATHPARTICLE,
|
||||
eType_ENDERPARTICLE,
|
||||
|
||||
eType_FIREWORKSSTARTERPARTICLE,
|
||||
eType_FIREWORKSSPARKPARTICLE,
|
||||
eType_FIREWORKSOVERLAYPARTICLE,
|
||||
|
||||
// === Tile Entities === //
|
||||
|
||||
eTYPE_TILEENTITY = BIT_TILE_ENTITY,
|
||||
|
||||
eTYPE_CHESTTILEENTITY = eTYPE_TILEENTITY | 0x01,
|
||||
eTYPE_MOBSPAWNERTILEENTITY = eTYPE_TILEENTITY | 0x02,
|
||||
eTYPE_FURNACETILEENTITY = eTYPE_TILEENTITY | 0x03,
|
||||
eTYPE_SIGNTILEENTITY = eTYPE_TILEENTITY | 0x04,
|
||||
eTYPE_MUSICTILEENTITY = eTYPE_TILEENTITY | 0x05,
|
||||
eTYPE_RECORDPLAYERTILE = eTYPE_TILEENTITY | 0x06,
|
||||
eTYPE_PISTONPIECEENTITY = eTYPE_TILEENTITY | 0x07,
|
||||
eTYPE_BREWINGSTANDTILEENTITY = eTYPE_TILEENTITY | 0x08,
|
||||
eTYPE_ENCHANTMENTTABLEENTITY = eTYPE_TILEENTITY | 0x09,
|
||||
eTYPE_THEENDPORTALTILEENTITY = eTYPE_TILEENTITY | 0x0A,
|
||||
eTYPE_SKULLTILEENTITY = eTYPE_TILEENTITY | 0x0B,
|
||||
eTYPE_ENDERCHESTTILEENTITY = eTYPE_TILEENTITY | 0x0C,
|
||||
eTYPE_BEACONTILEENTITY = eTYPE_TILEENTITY | 0x0D,
|
||||
eTYPE_COMMANDBLOCKTILEENTITY = eTYPE_TILEENTITY | 0x0E,
|
||||
eTYPE_COMPARATORTILEENTITY = eTYPE_TILEENTITY | 0x0F,
|
||||
eTYPE_DAYLIGHTDETECTORTILEENTITY = eTYPE_TILEENTITY | 0x10,
|
||||
eTYPE_HOPPERTILEENTITY = eTYPE_TILEENTITY | 0x11,
|
||||
|
||||
eTYPE_DISPENSERTILEENTITY = eTYPE_TILEENTITY | BIT_DISPENSERTILEENTITY,
|
||||
eTYPE_DROPPERTILEENTITY = eTYPE_DISPENSERTILEENTITY | 0x1,
|
||||
|
||||
// === Never used === //
|
||||
// exists to ensure all later entities don't match the bitmasks above
|
||||
|
||||
eTYPE_OTHERS = BIT_OTHER_NOT_ENTITIES,
|
||||
|
||||
eType_NODE,
|
||||
eType_ITEM,
|
||||
eType_ITEMINSTANCE,
|
||||
eType_MAPITEM,
|
||||
eType_TILE,
|
||||
eType_FIRETILE,
|
||||
};
|
||||
|
||||
inline bool eTYPE_DERIVED_FROM(eINSTANCEOF super, eINSTANCEOF sub) {
|
||||
if ((super & 0x3F) != 0x00)
|
||||
return super == sub;
|
||||
else
|
||||
return (super & sub) == super;
|
||||
}
|
||||
|
||||
inline bool eTYPE_FLAGSET(eINSTANCEOF flag, eINSTANCEOF claz) {
|
||||
return (flag & claz) == flag;
|
||||
}
|
||||
|
||||
/// FOR CHECKING ///
|
||||
|
||||
#if !(defined _WINDOWS64)
|
||||
|
||||
class SubClass {
|
||||
static void checkDerivations() {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class SubClass {
|
||||
public:
|
||||
bool m_isTerminal;
|
||||
const std::string m_name;
|
||||
const eINSTANCEOF m_id;
|
||||
std::vector<eINSTANCEOF> m_parents;
|
||||
|
||||
static std::unordered_map<eINSTANCEOF, SubClass*> s_ids;
|
||||
|
||||
SubClass(const std::string& name, eINSTANCEOF id) : m_name(name), m_id(id) {
|
||||
s_ids.insert(std::pair<eINSTANCEOF, SubClass*>(id, this));
|
||||
m_isTerminal = true;
|
||||
}
|
||||
|
||||
SubClass* addParent(eINSTANCEOF id) {
|
||||
SubClass* parent = s_ids.at(id);
|
||||
parent->m_isTerminal = false;
|
||||
|
||||
m_parents.push_back(id);
|
||||
|
||||
for (auto itr = parent->m_parents.begin();
|
||||
itr != parent->m_parents.end(); itr++) {
|
||||
m_parents.push_back(*itr);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
bool justFlag() { return (m_id & 0xF00000) == m_id; }
|
||||
|
||||
#define SUBCLASS(x) (new SubClass(#x, x))
|
||||
|
||||
static void checkDerivations() {
|
||||
std::vector<SubClass*>* classes = new std::vector<SubClass*>();
|
||||
|
||||
classes->push_back(SUBCLASS(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(SUBCLASS(eTYPE_ENEMY));
|
||||
classes->push_back(SUBCLASS(eTYPE_PROJECTILE));
|
||||
|
||||
classes->push_back(SUBCLASS(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_LIVINGENTITY)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_MOB)->addParent(eTYPE_LIVINGENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_PATHFINDER_MOB)->addParent(eTYPE_MOB));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_AGABLE_MOB)->addParent(eTYPE_PATHFINDER_MOB));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_VILLAGER)->addParent(eTYPE_AGABLE_MOB));
|
||||
classes->push_back(SUBCLASS(eTYPE_ANIMAL)->addParent(eTYPE_AGABLE_MOB));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_TAMABLE_ANIMAL)->addParent(eTYPE_ANIMAL));
|
||||
classes->push_back(SUBCLASS(eTYPE_OCELOT)
|
||||
->addParent(eTYPE_TAMABLE_ANIMAL)
|
||||
->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_WOLF)->addParent(eTYPE_TAMABLE_ANIMAL));
|
||||
classes->push_back(SUBCLASS(eTYPE_HORSE)
|
||||
->addParent(eTYPE_ANIMAL)
|
||||
->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(SUBCLASS(eTYPE_SHEEP)
|
||||
->addParent(eTYPE_ANIMAL)
|
||||
->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(SUBCLASS(eTYPE_PIG)
|
||||
->addParent(eTYPE_ANIMAL)
|
||||
->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(SUBCLASS(eTYPE_CHICKEN)->addParent(eTYPE_ANIMAL));
|
||||
classes->push_back(SUBCLASS(eTYPE_COW)
|
||||
->addParent(eTYPE_ANIMAL)
|
||||
->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(SUBCLASS(eTYPE_MUSHROOMCOW)->addParent(eTYPE_COW));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_WATERANIMAL)->addParent(eTYPE_PATHFINDER_MOB));
|
||||
classes->push_back(SUBCLASS(eTYPE_SQUID)->addParent(eTYPE_WATERANIMAL));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_GOLEM)->addParent(eTYPE_PATHFINDER_MOB));
|
||||
classes->push_back(SUBCLASS(eTYPE_SNOWMAN)
|
||||
->addParent(eTYPE_GOLEM)
|
||||
->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_VILLAGERGOLEM)->addParent(eTYPE_GOLEM));
|
||||
classes->push_back(SUBCLASS(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_ENEMY)
|
||||
->addParent(eTYPE_PATHFINDER_MOB));
|
||||
classes->push_back(SUBCLASS(eTYPE_SPIDER)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_CAVESPIDER)->addParent(eTYPE_SPIDER));
|
||||
classes->push_back(SUBCLASS(eTYPE_ZOMBIE)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_PIGZOMBIE)->addParent(eTYPE_ZOMBIE));
|
||||
classes->push_back(SUBCLASS(eTYPE_CREEPER)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_GIANT)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_SKELETON)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_ENDERMAN)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_SILVERFISH)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_BLAZE)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_WITCH)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_WITHERBOSS)
|
||||
->addParent(eTYPE_MONSTER)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_AMBIENT)->addParent(eTYPE_MOB));
|
||||
classes->push_back(SUBCLASS(eTYPE_BAT)
|
||||
->addParent(eTYPE_AMBIENT)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG));
|
||||
classes->push_back(SUBCLASS(eTYPE_FLYING_MOB)->addParent(eTYPE_MOB));
|
||||
classes->push_back(SUBCLASS(eTYPE_GHAST)
|
||||
->addParent(eTYPE_FLYING_MOB)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)
|
||||
->addParent(eTYPE_ENEMY));
|
||||
classes->push_back(SUBCLASS(eTYPE_SLIME)
|
||||
->addParent(eTYPE_MOB)
|
||||
->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)
|
||||
->addParent(eTYPE_ENEMY));
|
||||
classes->push_back(SUBCLASS(eTYPE_LAVASLIME)->addParent(eTYPE_SLIME));
|
||||
classes->push_back(SUBCLASS(eTYPE_ENDERDRAGON)->addParent(eTYPE_MOB));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_PLAYER)->addParent(eTYPE_LIVINGENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_SERVERPLAYER)->addParent(eTYPE_PLAYER));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_REMOTEPLAYER)->addParent(eTYPE_PLAYER));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_LOCALPLAYER)->addParent(eTYPE_PLAYER));
|
||||
classes->push_back(SUBCLASS(eTYPE_MINECART)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MINECART_RIDEABLE)->addParent(eTYPE_MINECART));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MINECART_SPAWNER)->addParent(eTYPE_MINECART));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MINECART_FURNACE)->addParent(eTYPE_MINECART));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MINECART_TNT)->addParent(eTYPE_MINECART));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MINECART_CONTAINER)->addParent(eTYPE_MINECART));
|
||||
classes->push_back(SUBCLASS(eTYPE_MINECART_CHEST)
|
||||
->addParent(eTYPE_MINECART_CONTAINER));
|
||||
classes->push_back(SUBCLASS(eTYPE_MINECART_HOPPER)
|
||||
->addParent(eTYPE_MINECART_CONTAINER));
|
||||
classes->push_back(SUBCLASS(eTYPE_FIREBALL)
|
||||
->addParent(eTYPE_ENTITY)
|
||||
->addParent(eTYPE_PROJECTILE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_DRAGON_FIREBALL)->addParent(eTYPE_FIREBALL));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_WITHER_SKULL)->addParent(eTYPE_FIREBALL));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_LARGE_FIREBALL)->addParent(eTYPE_FIREBALL));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_SMALL_FIREBALL)->addParent(eTYPE_FIREBALL));
|
||||
classes->push_back(SUBCLASS(eTYPE_THROWABLE)
|
||||
->addParent(eTYPE_ENTITY)
|
||||
->addParent(eTYPE_PROJECTILE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_SNOWBALL)->addParent(eTYPE_THROWABLE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_THROWNEGG)->addParent(eTYPE_THROWABLE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_THROWNENDERPEARL)->addParent(eTYPE_THROWABLE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_THROWNPOTION)->addParent(eTYPE_THROWABLE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_THROWNEXPBOTTLE)->addParent(eTYPE_THROWABLE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_HANGING_ENTITY)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_PAINTING)->addParent(eTYPE_HANGING_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_ITEM_FRAME)->addParent(eTYPE_HANGING_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_LEASHFENCEKNOT)->addParent(eTYPE_HANGING_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_GLOBAL_ENTITY)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_LIGHTNINGBOLT)->addParent(eTYPE_GLOBAL_ENTITY));
|
||||
|
||||
// classes->push_back( SUBCLASS(eTYPE_OTHER_ENTITIES )->addParent(
|
||||
// eTYPE_ENTITY ) );
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_EXPERIENCEORB)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_EYEOFENDERSIGNAL)
|
||||
->addParent(eTYPE_ENTITY)
|
||||
->addParent(eTYPE_PROJECTILE));
|
||||
classes->push_back(SUBCLASS(eTYPE_FIREWORKS_ROCKET)
|
||||
->addParent(eTYPE_ENTITY)
|
||||
->addParent(eTYPE_PROJECTILE));
|
||||
classes->push_back(SUBCLASS(eTYPE_FISHINGHOOK)
|
||||
->addParent(eTYPE_ENTITY)
|
||||
->addParent(eTYPE_PROJECTILE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_DELAYEDRELEASE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_BOAT)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_FALLINGTILE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_ITEMENTITY)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_PRIMEDTNT)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_ARROW)
|
||||
->addParent(eTYPE_ENTITY)
|
||||
->addParent(eTYPE_PROJECTILE));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MULTIENTITY_MOB_PART)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_NETHER_SPHERE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_ENDER_CRYSTAL)->addParent(eTYPE_ENTITY));
|
||||
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_BREAKINGITEMPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_BUBBLEPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_EXPLODEPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_FLAMEPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_FOOTSTEPPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_HEARTPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_LAVAPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_NOTEPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_NETHERPORTALPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_REDDUSTPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_SMOKEPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_SNOWSHOVELPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_SPLASHPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_TAKEANIMATIONPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_TERRAINPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_WATERDROPPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_CRITPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_CRITPARTICLE2)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_HUGEEXPLOSIONPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_HUGEEXPLOSIONSEEDPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eType_PLAYERCLOUDPARTICLEPARTICLE)
|
||||
->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_SUSPENDEDPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_SUSPENDEDTOWNPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_DRIPPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_ENCHANTMENTTABLEPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_SPELLPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_DRAGONBREATHPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_ENDERPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_FIREWORKSSTARTERPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_FIREWORKSSPARKPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eType_FIREWORKSOVERLAYPARTICLE)->addParent(eTYPE_ENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_CHESTTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MOBSPAWNERTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_FURNACETILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_SIGNTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_MUSICTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_RECORDPLAYERTILE)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_PISTONPIECEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_BREWINGSTANDTILEENTITY)
|
||||
->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_ENCHANTMENTTABLEENTITY)
|
||||
->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_THEENDPORTALTILEENTITY)
|
||||
->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_SKULLTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_ENDERCHESTTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_BEACONTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_COMMANDBLOCKTILEENTITY)
|
||||
->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_COMPARATORTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_DAYLIGHTDETECTORTILEENTITY)
|
||||
->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_HOPPERTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(
|
||||
SUBCLASS(eTYPE_DISPENSERTILEENTITY)->addParent(eTYPE_TILEENTITY));
|
||||
classes->push_back(SUBCLASS(eTYPE_DROPPERTILEENTITY)
|
||||
->addParent(eTYPE_DISPENSERTILEENTITY));
|
||||
|
||||
// classes->push_back( SUBCLASS(eTYPE_OTHERS) );
|
||||
classes->push_back(SUBCLASS(eType_NODE));
|
||||
classes->push_back(SUBCLASS(eType_ITEM));
|
||||
classes->push_back(SUBCLASS(eType_ITEMINSTANCE));
|
||||
classes->push_back(SUBCLASS(eType_MAPITEM));
|
||||
classes->push_back(SUBCLASS(eType_TILE));
|
||||
classes->push_back(SUBCLASS(eType_FIRETILE));
|
||||
|
||||
std::vector<std::pair<SubClass*, SubClass*> > m_falsePositives;
|
||||
std::vector<std::pair<SubClass*, SubClass*> > m_falseNegatives;
|
||||
|
||||
std::vector<SubClass*>::iterator it1;
|
||||
for (it1 = classes->begin(); it1 != classes->end(); it1++) {
|
||||
SubClass* current = *it1;
|
||||
// if ( current->justFlag() ) continue;
|
||||
|
||||
std::vector<SubClass*>::iterator it2;
|
||||
for (it2 = classes->begin(); it2 != classes->end(); it2++) {
|
||||
SubClass* comparing = *it2;
|
||||
// if ( comparing->justFlag() ) continue;
|
||||
|
||||
// We shouldn't be comparing to leaf classes anyway.
|
||||
// if ( comparing->m_isTerminal ) continue;
|
||||
|
||||
eINSTANCEOF typeCurr, typeComp;
|
||||
typeCurr = current->m_id;
|
||||
typeComp = comparing->m_id;
|
||||
|
||||
bool shouldDerive, doesDerive;
|
||||
|
||||
{
|
||||
std::vector<eINSTANCEOF>::iterator it3;
|
||||
it3 = find(current->m_parents.begin(),
|
||||
current->m_parents.end(), typeComp);
|
||||
shouldDerive = (typeComp == typeCurr) ||
|
||||
(it3 != current->m_parents.end());
|
||||
}
|
||||
|
||||
doesDerive = eTYPE_DERIVED_FROM(typeComp, typeCurr);
|
||||
|
||||
if (shouldDerive != doesDerive) {
|
||||
std::vector<std::pair<SubClass*, SubClass*> >* errorArray;
|
||||
if (shouldDerive)
|
||||
errorArray = &m_falseNegatives;
|
||||
else
|
||||
errorArray = &m_falsePositives;
|
||||
|
||||
errorArray->push_back(
|
||||
std::pair<SubClass*, SubClass*>(comparing, current));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<SubClass*, SubClass*> >::iterator itrErr;
|
||||
for (itrErr = m_falsePositives.begin();
|
||||
itrErr != m_falsePositives.end(); itrErr++) {
|
||||
SubClass *sub = itrErr->first, *super = itrErr->second;
|
||||
printf("[Class.h] Error: '%s' incorrectly derives from '%s'.\n",
|
||||
sub->m_name.c_str(), super->m_name.c_str());
|
||||
}
|
||||
for (itrErr = m_falseNegatives.begin();
|
||||
itrErr != m_falseNegatives.end(); itrErr++) {
|
||||
SubClass *sub = itrErr->first, *super = itrErr->second;
|
||||
printf("[Class.h] Error: '%s' doesn't derive '%s'.\n",
|
||||
sub->m_name.c_str(), super->m_name.c_str());
|
||||
}
|
||||
|
||||
if ((m_falsePositives.size() > 0) || (m_falseNegatives.size() > 0)) {
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
15
minecraft/java/include/java/Color.h
Normal file
15
minecraft/java/include/java/Color.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
class Color {
|
||||
private:
|
||||
int colour;
|
||||
|
||||
public:
|
||||
// Creates an opaque sRGB color with the specified red, green, and blue
|
||||
// values in the range (0.0 - 1.0).
|
||||
Color(float r, float g, float b);
|
||||
Color(int r, int g, int b);
|
||||
|
||||
static Color getHSBColor(float h, float s, float b);
|
||||
int getRGB();
|
||||
};
|
||||
25
minecraft/java/include/java/Exceptions.h
Normal file
25
minecraft/java/include/java/Exceptions.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
class EOFException : public std::exception {};
|
||||
|
||||
class IllegalArgumentException : public std::exception {
|
||||
public:
|
||||
std::wstring information;
|
||||
|
||||
IllegalArgumentException(const std::wstring& information);
|
||||
};
|
||||
|
||||
class IOException : public std::exception {
|
||||
public:
|
||||
std::wstring information;
|
||||
|
||||
IOException(const std::wstring& information);
|
||||
};
|
||||
|
||||
class RuntimeException : public std::exception {
|
||||
public:
|
||||
RuntimeException(const std::wstring& information);
|
||||
};
|
||||
58
minecraft/java/include/java/File.h
Normal file
58
minecraft/java/include/java/File.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
// 4J Stu - Represents java standard library class
|
||||
|
||||
class FileFilter;
|
||||
|
||||
class File {
|
||||
public:
|
||||
// The system-dependent path-separator character
|
||||
static const wchar_t pathSeparator;
|
||||
|
||||
// 4J Jev, the start of the file root
|
||||
static const std::wstring pathRoot;
|
||||
|
||||
File() { m_abstractPathName = L""; }
|
||||
|
||||
File(const File& parent, const std::wstring& child);
|
||||
File(const std::wstring& pathname);
|
||||
File(const std::wstring& parent, const std::wstring& child);
|
||||
bool _delete();
|
||||
bool mkdir() const;
|
||||
bool mkdirs() const;
|
||||
bool exists() const;
|
||||
bool isFile() const;
|
||||
bool renameTo(File dest);
|
||||
std::vector<File*>* listFiles() const; // Array
|
||||
std::vector<File*>* listFiles(FileFilter* filter) const;
|
||||
bool isDirectory() const;
|
||||
int64_t length();
|
||||
int64_t lastModified();
|
||||
const std::wstring getPath() const; // 4J Jev: TODO
|
||||
std::wstring getName() const;
|
||||
|
||||
static int hash_fnct(const File& k);
|
||||
static bool eq_test(const File& x, const File& y);
|
||||
|
||||
private:
|
||||
void _init();
|
||||
std::wstring m_abstractPathName;
|
||||
|
||||
// 4J Jev, just helper functions, change between paths and
|
||||
// std::vector<string>
|
||||
// File(std::vector<std::wstring> *path);
|
||||
};
|
||||
|
||||
struct FileKeyHash {
|
||||
int operator()(const File& k) const { return File::hash_fnct(k); }
|
||||
};
|
||||
|
||||
struct FileKeyEq {
|
||||
bool operator()(const File& x, const File& y) const {
|
||||
return File::eq_test(x, y);
|
||||
}
|
||||
};
|
||||
9
minecraft/java/include/java/FileFilter.h
Normal file
9
minecraft/java/include/java/FileFilter.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
class File;
|
||||
|
||||
// 4J Jev, java library interface.
|
||||
class FileFilter {
|
||||
public:
|
||||
virtual bool accept(File* dir) = 0;
|
||||
};
|
||||
11
minecraft/java/include/java/FilenameFilter.h
Normal file
11
minecraft/java/include/java/FilenameFilter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class File;
|
||||
|
||||
// 4J Jev, java lirary interface.
|
||||
class FilenameFilter {
|
||||
public:
|
||||
virtual bool accept(File* dir, const std::wstring& name) = 0;
|
||||
};
|
||||
18
minecraft/java/include/java/FloatBuffer.h
Normal file
18
minecraft/java/include/java/FloatBuffer.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "Buffer.h"
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class FloatBuffer : public Buffer {
|
||||
private:
|
||||
float* buffer;
|
||||
|
||||
public:
|
||||
FloatBuffer(unsigned int capacity);
|
||||
FloatBuffer(unsigned int capacity, float* backingArray);
|
||||
virtual ~FloatBuffer();
|
||||
|
||||
FloatBuffer* flip();
|
||||
FloatBuffer* put(float f);
|
||||
void get(arrayWithLength<float>* dst);
|
||||
float* _getDataPointer() { return buffer; }
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "OutputStream.h"
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class BufferedOutputStream : public OutputStream {
|
||||
private:
|
||||
OutputStream* stream;
|
||||
|
||||
protected:
|
||||
byteArray buf; // The internal buffer where data is stored.
|
||||
unsigned int count; // The number of valid bytes in the buffer.
|
||||
|
||||
public:
|
||||
BufferedOutputStream(OutputStream* out, int size);
|
||||
~BufferedOutputStream();
|
||||
|
||||
virtual void flush();
|
||||
virtual void close();
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(unsigned int b);
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
class BufferedReader : public Reader {
|
||||
private:
|
||||
Reader* reader;
|
||||
wchar_t* buffer;
|
||||
|
||||
unsigned int readMark;
|
||||
unsigned int bufferedMark;
|
||||
unsigned int bufferSize;
|
||||
bool eofReached;
|
||||
|
||||
static const unsigned int BUFFER_MORE_AMOUNT = 64;
|
||||
void bufferMore();
|
||||
|
||||
public:
|
||||
BufferedReader(Reader* in);
|
||||
virtual ~BufferedReader();
|
||||
|
||||
virtual void close();
|
||||
virtual int read();
|
||||
virtual int read(wchar_t cbuf[], unsigned int off, unsigned int len);
|
||||
std::wstring readLine();
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class
|
||||
|
||||
#include "InputStream.h"
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class ByteArrayInputStream : public InputStream {
|
||||
protected:
|
||||
byteArray buf; // An array of bytes that was provided by the creator of the
|
||||
// stream.
|
||||
unsigned int count; // The index one greater than the last valid character
|
||||
// in the input stream buffer.
|
||||
unsigned int mark; // The currently marked position in the stream.
|
||||
unsigned int pos; // The index of the next character to read from the input
|
||||
// stream buffer.
|
||||
|
||||
public:
|
||||
ByteArrayInputStream(byteArray buf, unsigned int offset,
|
||||
unsigned int length);
|
||||
ByteArrayInputStream(byteArray buf);
|
||||
virtual ~ByteArrayInputStream();
|
||||
virtual int read();
|
||||
virtual int read(byteArray b);
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual int64_t skip(int64_t n);
|
||||
|
||||
// 4J Stu Added - Sometimes we don't want to delete the data on destroying
|
||||
// this
|
||||
void reset() {
|
||||
buf = byteArray();
|
||||
count = 0;
|
||||
mark = 0;
|
||||
pos = 0;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "OutputStream.h"
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class ByteArrayOutputStream : public OutputStream {
|
||||
// Note - when actually implementing, byteArray will need to grow as data is
|
||||
// written
|
||||
public:
|
||||
byteArray buf; // The buffer where data is stored.
|
||||
|
||||
protected:
|
||||
unsigned int count; // The number of valid bytes in the buffer.
|
||||
|
||||
public:
|
||||
ByteArrayOutputStream();
|
||||
ByteArrayOutputStream(unsigned int size);
|
||||
virtual ~ByteArrayOutputStream();
|
||||
|
||||
virtual void flush() {}
|
||||
virtual void write(unsigned int b);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual byteArray toByteArray();
|
||||
|
||||
void reset() { count = 0; }
|
||||
unsigned int size() { return count; }
|
||||
};
|
||||
23
minecraft/java/include/java/InputOutputStream/DataInput.h
Normal file
23
minecraft/java/include/java/InputOutputStream/DataInput.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class DataInput {
|
||||
public:
|
||||
virtual int read() = 0;
|
||||
virtual int read(byteArray b) = 0;
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length) = 0;
|
||||
virtual bool readBoolean() = 0;
|
||||
virtual uint8_t readByte() = 0;
|
||||
virtual unsigned char readUnsignedByte() = 0;
|
||||
virtual bool readFully(byteArray a) = 0;
|
||||
virtual double readDouble() = 0;
|
||||
virtual float readFloat() = 0;
|
||||
virtual int readInt() = 0;
|
||||
virtual int64_t readLong() = 0;
|
||||
virtual short readShort() = 0;
|
||||
virtual wchar_t readChar() = 0;
|
||||
virtual std::wstring readUTF() = 0;
|
||||
virtual unsigned long long readPlayerUID() = 0; // 4J Added
|
||||
virtual int skipBytes(int n) = 0;
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class (although we miss out an
|
||||
// intermediate inheritance class that we don't care about)
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "InputStream.h"
|
||||
#include "DataInput.h"
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class DataInputStream : public InputStream, public DataInput {
|
||||
private:
|
||||
InputStream* stream;
|
||||
|
||||
public:
|
||||
DataInputStream(InputStream* in);
|
||||
virtual int read();
|
||||
virtual int read(byteArray b);
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual bool readBoolean();
|
||||
virtual uint8_t readByte();
|
||||
virtual unsigned char readUnsignedByte();
|
||||
virtual wchar_t readChar();
|
||||
virtual bool readFully(byteArray b);
|
||||
virtual bool readFully(charArray b);
|
||||
virtual double readDouble();
|
||||
virtual float readFloat();
|
||||
virtual int readInt();
|
||||
virtual int64_t readLong();
|
||||
virtual short readShort();
|
||||
virtual unsigned short readUnsignedShort();
|
||||
virtual std::wstring readUTF();
|
||||
void deleteChildStream();
|
||||
virtual int readUTFChar();
|
||||
virtual unsigned long long readPlayerUID(); // 4J Added
|
||||
virtual int64_t skip(int64_t n);
|
||||
virtual int skipBytes(int n);
|
||||
};
|
||||
22
minecraft/java/include/java/InputOutputStream/DataOutput.h
Normal file
22
minecraft/java/include/java/InputOutputStream/DataOutput.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
class DataOutput {
|
||||
public:
|
||||
virtual void write(unsigned int b) = 0;
|
||||
virtual void write(byteArray b) = 0;
|
||||
virtual void write(byteArray b, unsigned int offset,
|
||||
unsigned int length) = 0;
|
||||
virtual void writeByte(uint8_t a) = 0;
|
||||
virtual void writeDouble(double a) = 0;
|
||||
virtual void writeFloat(float a) = 0;
|
||||
virtual void writeInt(int a) = 0;
|
||||
virtual void writeLong(int64_t a) = 0;
|
||||
virtual void writeShort(short a) = 0;
|
||||
virtual void writeBoolean(bool v) = 0;
|
||||
virtual void writeChar(wchar_t v) = 0;
|
||||
virtual void writeChars(const std::wstring& s) = 0;
|
||||
virtual void writeUTF(const std::wstring& a) = 0;
|
||||
virtual void writePlayerUID(unsigned long long player) = 0; // 4J Added
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class (although we miss out an
|
||||
// intermediate inheritance class that we don't care about)
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
|
||||
#include "OutputStream.h"
|
||||
#include "DataOutput.h"
|
||||
|
||||
class DataOutputStream : public OutputStream, public DataOutput {
|
||||
private:
|
||||
OutputStream* stream;
|
||||
|
||||
protected:
|
||||
int written; // The number of bytes written to the data output stream so
|
||||
// far.
|
||||
|
||||
public:
|
||||
DataOutputStream(OutputStream* out);
|
||||
|
||||
// 4J Stu Added
|
||||
void deleteChildStream();
|
||||
|
||||
virtual void write(unsigned int b);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual void writeByte(uint8_t a);
|
||||
virtual void writeDouble(double a);
|
||||
virtual void writeFloat(float a);
|
||||
virtual void writeInt(int a);
|
||||
virtual void writeLong(int64_t a);
|
||||
virtual void writeShort(short a);
|
||||
virtual void writeUnsignedShort(unsigned short a);
|
||||
virtual void writeChar(wchar_t a);
|
||||
virtual void writeChars(const std::wstring& a);
|
||||
virtual void writeBoolean(bool b);
|
||||
virtual void writeUTF(const std::wstring& a);
|
||||
virtual void writePlayerUID(unsigned long long player);
|
||||
virtual void flush();
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
#include "InputStream.h"
|
||||
|
||||
class File;
|
||||
|
||||
class FileInputStream : public InputStream {
|
||||
public:
|
||||
FileInputStream(const File& file);
|
||||
virtual ~FileInputStream();
|
||||
virtual int read();
|
||||
virtual int read(byteArray b);
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual int64_t skip(int64_t n);
|
||||
|
||||
private:
|
||||
std::FILE* m_fileHandle;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard lib abstract
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
#include "OutputStream.h"
|
||||
|
||||
class File;
|
||||
|
||||
class FileOutputStream : public OutputStream {
|
||||
public:
|
||||
FileOutputStream(const File& file);
|
||||
virtual ~FileOutputStream();
|
||||
virtual void write(unsigned int b);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
|
||||
private:
|
||||
std::FILE* m_fileHandle;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
// 4J Stu - We are not using GZIP compression, so this is just a pass through
|
||||
// class
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
#include "InputStream.h"
|
||||
|
||||
class GZIPInputStream : public InputStream {
|
||||
private:
|
||||
InputStream* stream;
|
||||
|
||||
public:
|
||||
GZIPInputStream(InputStream* out) : stream(out) {};
|
||||
virtual int read() { return stream->read(); };
|
||||
virtual int read(byteArray b) { return stream->read(b); };
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length) {
|
||||
return stream->read(b, offset, length);
|
||||
};
|
||||
virtual void close() { return stream->close(); };
|
||||
virtual int64_t skip(int64_t n) { return 0; };
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
// 4J Stu - We are not using GZIP compression, so this is just a pass through
|
||||
// class
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
#include "OutputStream.h"
|
||||
|
||||
class GZIPOutputStream : public OutputStream {
|
||||
private:
|
||||
OutputStream* stream;
|
||||
|
||||
public:
|
||||
GZIPOutputStream(OutputStream* out) : stream(out) {};
|
||||
virtual void write(unsigned int b) { stream->write(b); };
|
||||
virtual void write(byteArray b) { stream->write(b); };
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length) {
|
||||
stream->write(b, offset, length);
|
||||
};
|
||||
virtual void close() { stream->close(); };
|
||||
virtual void flush() {}
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputStream.h"
|
||||
#include "ByteArrayInputStream.h"
|
||||
#include "DataInput.h"
|
||||
#include "DataInputStream.h"
|
||||
#include "FileInputStream.h"
|
||||
#include "GZIPInputStream.h"
|
||||
|
||||
#include "OutputStream.h"
|
||||
#include "ByteArrayOutputStream.h"
|
||||
#include "DataOutput.h"
|
||||
#include "BufferedOutputStream.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "FileOutputStream.h"
|
||||
#include "GZIPOutputStream.h"
|
||||
|
||||
#include "Reader.h"
|
||||
#include "BufferedReader.h"
|
||||
#include "InputStreamReader.h"
|
||||
21
minecraft/java/include/java/InputOutputStream/InputStream.h
Normal file
21
minecraft/java/include/java/InputOutputStream/InputStream.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
// 4J Stu - Represents Java standard lib abstract
|
||||
|
||||
class InputStream {
|
||||
public:
|
||||
virtual ~InputStream() {}
|
||||
|
||||
virtual int read() = 0;
|
||||
virtual int read(byteArray b) = 0;
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual int64_t skip(int64_t n) = 0;
|
||||
|
||||
static InputStream* getResourceAsStream(const std::wstring& fileName);
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reader.h"
|
||||
#include "DataInputStream.h"
|
||||
|
||||
class InputStream;
|
||||
|
||||
class InputStreamReader : public Reader {
|
||||
private:
|
||||
DataInputStream* stream;
|
||||
|
||||
public:
|
||||
InputStreamReader(InputStream* in);
|
||||
|
||||
virtual void close();
|
||||
virtual int read();
|
||||
virtual int read(wchar_t cbuf[], unsigned int offset, unsigned int length);
|
||||
};
|
||||
17
minecraft/java/include/java/InputOutputStream/OutputStream.h
Normal file
17
minecraft/java/include/java/InputOutputStream/OutputStream.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
// 4J Stu - Represents Java standard lib abstract
|
||||
|
||||
class OutputStream {
|
||||
public:
|
||||
virtual ~OutputStream() {}
|
||||
|
||||
virtual void write(unsigned int b) = 0;
|
||||
virtual void write(byteArray b) = 0;
|
||||
virtual void write(byteArray b, unsigned int offset,
|
||||
unsigned int length) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual void flush() = 0;
|
||||
};
|
||||
13
minecraft/java/include/java/InputOutputStream/Reader.h
Normal file
13
minecraft/java/include/java/InputOutputStream/Reader.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
virtual ~Reader() {}
|
||||
|
||||
virtual void close() = 0; // Closes the stream and releases any system
|
||||
// resources associated with it.
|
||||
virtual int read() = 0; // Reads a single character.
|
||||
virtual int read(
|
||||
wchar_t cbuf[], unsigned int off,
|
||||
unsigned int len) = 0; // Reads characters into a portion of an array.
|
||||
};
|
||||
23
minecraft/java/include/java/IntBuffer.h
Normal file
23
minecraft/java/include/java/IntBuffer.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
#include "Buffer.h"
|
||||
|
||||
class IntBuffer : public Buffer {
|
||||
private:
|
||||
int* buffer;
|
||||
|
||||
public:
|
||||
IntBuffer(unsigned int capacity);
|
||||
IntBuffer(unsigned int capacity, int* backingArray);
|
||||
virtual ~IntBuffer();
|
||||
|
||||
virtual IntBuffer* flip();
|
||||
int get(unsigned int index);
|
||||
int* getBuffer();
|
||||
IntBuffer* put(intArray* inputArray, unsigned int offset,
|
||||
unsigned int length);
|
||||
IntBuffer* put(intArray inputArray);
|
||||
IntBuffer* put(int i);
|
||||
};
|
||||
68
minecraft/java/include/java/JavaIntHash.h
Normal file
68
minecraft/java/include/java/JavaIntHash.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
// Java doesn't have a default hash value for ints, however, the hashmap itself
|
||||
// does some "supplemental" hashing, so our ints actually get hashed by code as
|
||||
// implemented below. std templates *do* have a standard hash for ints, but it
|
||||
// would appear to be a bit expensive so matching the java one for now anyway.
|
||||
// This code implements the supplemental hashing that happens in java so we can
|
||||
// match what their maps are doing with ints.
|
||||
|
||||
struct IntKeyHash {
|
||||
int operator()(const int& k) const {
|
||||
// 4jcraft added h to be unsigned, to not cast it later
|
||||
unsigned int h = k;
|
||||
h += ~(h << 9);
|
||||
h ^= (h >> 14);
|
||||
h += (h << 4);
|
||||
h ^= (h >> 10);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct IntKeyEq {
|
||||
bool operator()(const int& x, const int& y) const { return x == y; }
|
||||
};
|
||||
|
||||
// This hash functor is taken from the IntHashMap java class used by the game,
|
||||
// so that we can use a standard std hashmap with this hash rather than
|
||||
// implement the class itself
|
||||
struct IntKeyHash2 {
|
||||
int operator()(const int& k) const {
|
||||
unsigned int h = (unsigned int)k;
|
||||
h ^= (h >> 20) ^ (h >> 12);
|
||||
return (int)(h ^ (h >> 7) ^ (h >> 4));
|
||||
}
|
||||
};
|
||||
|
||||
// This hash functor is taken from the LongHashMap java class used by the game,
|
||||
// so that we can use a standard std hashmap with this hash rather than
|
||||
// implement the class itself
|
||||
struct LongKeyHash {
|
||||
int hash(const int& k) const {
|
||||
unsigned int h = (unsigned int)k;
|
||||
h ^= (h >> 20) ^ (h >> 12);
|
||||
return (int)(h ^ (h >> 7) ^ (h >> 4));
|
||||
}
|
||||
|
||||
int operator()(const int64_t& k) const {
|
||||
return hash((int)(k ^ (((uint64_t)k) >> 32)));
|
||||
}
|
||||
};
|
||||
|
||||
struct LongKeyEq {
|
||||
bool operator()(const int64_t& x, const int64_t& y) const { return x == y; }
|
||||
};
|
||||
|
||||
struct eINSTANCEOFKeyHash {
|
||||
int operator()(const eINSTANCEOF& k) const {
|
||||
unsigned int h = (unsigned int)k;
|
||||
h ^= (h >> 20) ^ (h >> 12);
|
||||
return (int)(h ^ (h >> 7) ^ (h >> 4));
|
||||
}
|
||||
};
|
||||
|
||||
struct eINSTANCEOFKeyEq {
|
||||
bool operator()(const eINSTANCEOF& x, const eINSTANCEOF& y) const {
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
18
minecraft/java/include/java/JavaMath.h
Normal file
18
minecraft/java/include/java/JavaMath.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "Random.h"
|
||||
|
||||
class Math {
|
||||
private:
|
||||
static Random rand;
|
||||
|
||||
public:
|
||||
static double random();
|
||||
static int64_t round(double d);
|
||||
static int _max(int a, int b);
|
||||
static float _max(float a, float b);
|
||||
static int _min(int a, int b);
|
||||
static float _min(float a, float b);
|
||||
|
||||
static float wrapDegrees(float input);
|
||||
static double wrapDegrees(double input);
|
||||
};
|
||||
24
minecraft/java/include/java/Random.h
Normal file
24
minecraft/java/include/java/Random.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class Random {
|
||||
private:
|
||||
int64_t seed;
|
||||
bool haveNextNextGaussian;
|
||||
double nextNextGaussian;
|
||||
|
||||
protected:
|
||||
int next(int bits);
|
||||
|
||||
public:
|
||||
Random();
|
||||
Random(int64_t seed);
|
||||
void setSeed(int64_t s);
|
||||
void nextBytes(uint8_t* bytes, unsigned int count);
|
||||
double nextDouble();
|
||||
double nextGaussian();
|
||||
int nextInt();
|
||||
int nextInt(int to);
|
||||
float nextFloat();
|
||||
int64_t nextLong();
|
||||
bool nextBoolean();
|
||||
};
|
||||
11
minecraft/java/include/java/Reference.h
Normal file
11
minecraft/java/include/java/Reference.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
template <class T>
|
||||
class Reference {
|
||||
private:
|
||||
T* obj;
|
||||
|
||||
public:
|
||||
T* get() { return obj; }
|
||||
Reference(T* i) { obj = i; }
|
||||
};
|
||||
46
minecraft/java/include/java/System.h
Normal file
46
minecraft/java/include/java/System.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
// 4J Jev, just thought it would be easier this way.
|
||||
#define ArrayCopyFunctionDeclaration(x) \
|
||||
static void arraycopy(arrayWithLength<x> src, unsigned int srcPos, \
|
||||
arrayWithLength<x>* dst, unsigned int dstPos, \
|
||||
unsigned int length);
|
||||
#define ArrayCopyFunctionDefinition(x) \
|
||||
void System::arraycopy(arrayWithLength<x> src, unsigned int srcPos, \
|
||||
arrayWithLength<x>* dst, unsigned int dstPos, \
|
||||
unsigned int length) { \
|
||||
arraycopy<x>(src, srcPos, dst, dstPos, length); \
|
||||
}
|
||||
|
||||
class System {
|
||||
template <class T>
|
||||
static void arraycopy(arrayWithLength<T> src, unsigned int srcPos,
|
||||
arrayWithLength<T>* dst, unsigned int dstPos,
|
||||
unsigned int length);
|
||||
|
||||
public:
|
||||
ArrayCopyFunctionDeclaration(uint8_t) ArrayCopyFunctionDeclaration(Node*)
|
||||
ArrayCopyFunctionDeclaration(Biome*) ArrayCopyFunctionDeclaration(int)
|
||||
|
||||
static int64_t nanoTime();
|
||||
static int64_t currentTimeMillis();
|
||||
static int64_t currentRealTimeMillis(); // 4J Added to get real-world time
|
||||
// for timestamps in saves
|
||||
|
||||
static void ReverseUSHORT(unsigned short* pusVal);
|
||||
static void ReverseSHORT(short* psVal);
|
||||
static void ReverseULONG(unsigned long* pulVal);
|
||||
static void ReverseULONG(unsigned int* pulVal);
|
||||
static void ReverseINT(int* piVal);
|
||||
static void ReverseULONGLONG(int64_t* pullVal);
|
||||
static void ReverseWCHARA(wchar_t* pwch, int iLen);
|
||||
};
|
||||
|
||||
#define MAKE_FOURCC(ch0, ch1, ch2, ch3) \
|
||||
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(ch0)) | \
|
||||
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(ch1)) << 8) | \
|
||||
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(ch2)) << 16) | \
|
||||
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(ch3)) << 24))
|
||||
35
minecraft/java/meson.build
Normal file
35
minecraft/java/meson.build
Normal file
@@ -0,0 +1,35 @@
|
||||
java_sources = files(
|
||||
'src/InputOutputStream/BufferedOutputStream.cpp',
|
||||
'src/InputOutputStream/BufferedReader.cpp',
|
||||
'src/InputOutputStream/ByteArrayInputStream.cpp',
|
||||
'src/InputOutputStream/ByteArrayOutputStream.cpp',
|
||||
'src/InputOutputStream/DataInputStream.cpp',
|
||||
'src/InputOutputStream/DataOutputStream.cpp',
|
||||
'src/InputOutputStream/FileInputStream.cpp',
|
||||
'src/InputOutputStream/FileOutputStream.cpp',
|
||||
'src/InputOutputStream/InputStream.cpp',
|
||||
'src/InputOutputStream/InputStreamReader.cpp',
|
||||
'src/Buffer.cpp',
|
||||
'src/ByteBuffer.cpp',
|
||||
'src/Class.cpp',
|
||||
'src/Color.cpp',
|
||||
'src/File.cpp',
|
||||
'src/FloatBuffer.cpp',
|
||||
'src/IntBuffer.cpp',
|
||||
'src/JavaMath.cpp',
|
||||
'src/Random.cpp',
|
||||
'src/system.cpp',
|
||||
# 'src/Socket.cpp',
|
||||
)
|
||||
|
||||
lib_java = static_library('java',
|
||||
java_sources,
|
||||
# TODO: remove the .. path once arrayWithLength are evaporated
|
||||
include_directories: include_directories('include/java'),
|
||||
cpp_args : global_cpp_args + global_cpp_defs,
|
||||
)
|
||||
|
||||
java_dep = declare_dependency(
|
||||
link_with : lib_java,
|
||||
include_directories: include_directories('include')
|
||||
)
|
||||
60
minecraft/java/src/Buffer.cpp
Normal file
60
minecraft/java/src/Buffer.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "Buffer.h"
|
||||
|
||||
Buffer::Buffer(unsigned int capacity)
|
||||
: m_capacity(capacity),
|
||||
m_position(0),
|
||||
m_limit(capacity),
|
||||
hasBackingArray(false) {}
|
||||
|
||||
// Clears this buffer. The position is set to zero, the limit is set to the
|
||||
// capacity, and the mark is discarded. This method does not actually erase the
|
||||
// data in the buffer, but it is named as if it did because it will most often
|
||||
// be used in situations in which that might as well be the case.
|
||||
//
|
||||
// Returns:
|
||||
// This buffer
|
||||
Buffer* Buffer::clear() {
|
||||
m_position = 0;
|
||||
m_limit = m_capacity;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Sets this buffer's limit. If the position is larger than the new limit then
|
||||
// it is set to the new limit. If the mark is defined and larger than the new
|
||||
// limit then it is discarded. Parameters: newLimit - The new limit value; must
|
||||
// be non-negative and no larger than this buffer's capacity Returns: This
|
||||
// buffer
|
||||
Buffer* Buffer::limit(unsigned int newLimit) {
|
||||
assert(newLimit <= m_capacity);
|
||||
|
||||
m_limit = newLimit;
|
||||
|
||||
if (m_position > newLimit) m_position = newLimit;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
unsigned int Buffer::limit() { return m_limit; }
|
||||
|
||||
// Sets this buffer's position. If the mark is defined and larger than the new
|
||||
// position then it is discarded. Parameters: newPosition - The new position
|
||||
// value; must be non-negative and no larger than the current limit Returns:
|
||||
// This buffer
|
||||
Buffer* Buffer::position(unsigned int newPosition) {
|
||||
assert(newPosition <= m_limit);
|
||||
|
||||
m_position = newPosition;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Returns this buffer's position.
|
||||
// Returns:
|
||||
// The position of this buffer
|
||||
unsigned int Buffer::position() { return m_position; }
|
||||
|
||||
// Returns the number of elements between the current position and the limit.
|
||||
// Returns:
|
||||
// The number of elements remaining in this buffer
|
||||
unsigned int Buffer::remaining() { return m_limit - m_position; }
|
||||
429
minecraft/java/src/ByteBuffer.cpp
Normal file
429
minecraft/java/src/ByteBuffer.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
|
||||
#include "IntBuffer.h"
|
||||
#include "FloatBuffer.h"
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
ByteBuffer::ByteBuffer(unsigned int capacity) : Buffer(capacity) {
|
||||
hasBackingArray = false;
|
||||
buffer = new uint8_t[capacity];
|
||||
memset(buffer, 0, sizeof(uint8_t) * capacity);
|
||||
byteOrder = BIGENDIAN;
|
||||
}
|
||||
|
||||
// Allocates a new direct byte buffer.
|
||||
// The new buffer's position will be zero, its limit will be its capacity, and
|
||||
// its mark will be undefined. Whether or not it has a backing array is
|
||||
// unspecified.
|
||||
//
|
||||
// Parameters:
|
||||
// capacity - The new buffer's capacity, in bytes
|
||||
// Returns:
|
||||
// The new byte buffer
|
||||
ByteBuffer* ByteBuffer::allocateDirect(int capacity) {
|
||||
return new ByteBuffer(capacity);
|
||||
}
|
||||
|
||||
ByteBuffer::ByteBuffer(unsigned int capacity, uint8_t* backingArray)
|
||||
: Buffer(capacity) {
|
||||
hasBackingArray = true;
|
||||
buffer = backingArray;
|
||||
}
|
||||
|
||||
ByteBuffer::~ByteBuffer() {
|
||||
if (!hasBackingArray) delete[] buffer;
|
||||
}
|
||||
|
||||
// Wraps a byte array into a buffer.
|
||||
// The new buffer will be backed by the given uint8_t array; that is,
|
||||
// modifications to the buffer will cause the array to be modified and vice
|
||||
// versa. The new buffer's capacity and limit will be array.length, its position
|
||||
// will be zero, and its mark will be undefined. Its backing array will be the
|
||||
// given array, and its array offset will be zero.
|
||||
//
|
||||
// Parameters:
|
||||
// array - The array that will back this buffer
|
||||
// Returns:
|
||||
// The new byte buffer
|
||||
ByteBuffer* ByteBuffer::wrap(byteArray& b) {
|
||||
return new ByteBuffer(b.length, b.data);
|
||||
}
|
||||
|
||||
// Allocates a new byte buffer.
|
||||
// The new buffer's position will be zero, its limit will be its capacity, and
|
||||
// its mark will be undefined. It will have a backing array, and its array
|
||||
// offset will be zero.
|
||||
//
|
||||
// Parameters:
|
||||
// capacity - The new buffer's capacity, in bytes
|
||||
// Returns:
|
||||
// The new byte buffer
|
||||
ByteBuffer* ByteBuffer::allocate(unsigned int capacity) {
|
||||
return new ByteBuffer(capacity);
|
||||
}
|
||||
|
||||
// Modifies this buffer's byte order.
|
||||
// Parameters:
|
||||
// bo - The new byte order, either BIGENDIAN or LITTLEENDIAN
|
||||
void ByteBuffer::order(ByteOrder bo) { byteOrder = bo; }
|
||||
|
||||
// Flips this buffer. The limit is set to the current position and then the
|
||||
// position is set to zero. If the mark is defined then it is discarded.
|
||||
//
|
||||
// Returns:
|
||||
// This buffer
|
||||
ByteBuffer* ByteBuffer::flip() {
|
||||
m_limit = m_position;
|
||||
m_position = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
// 4J Added so we can write this to a file
|
||||
uint8_t* ByteBuffer::getBuffer() { return buffer; }
|
||||
|
||||
int ByteBuffer::getSize() {
|
||||
// TODO 4J Stu - Should this be the capcity and not the limit?
|
||||
return m_limit;
|
||||
}
|
||||
// End 4J
|
||||
|
||||
// Absolute get method. Reads the byte at the given index.
|
||||
// Parameters:
|
||||
// index - The index from which the byte will be read
|
||||
// Returns:
|
||||
// The byte at the given index
|
||||
// Throws:
|
||||
// IndexOutOfBoundsException - If index is negative or not smaller than the
|
||||
// buffer's limit
|
||||
uint8_t ByteBuffer::get(int index) {
|
||||
assert(index < m_limit);
|
||||
assert(index >= 0);
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
// Relative get method for reading an int value.
|
||||
// Reads the next four bytes at this buffer's current position, composing them
|
||||
// into an int value according to the current byte order, and then increments
|
||||
// the position by four.
|
||||
//
|
||||
// Returns:
|
||||
// The int value at the buffer's current position
|
||||
int ByteBuffer::getInt() {
|
||||
assert(m_position + 3 < m_limit);
|
||||
|
||||
int value = 0;
|
||||
|
||||
int b1 = static_cast<int>(buffer[m_position]);
|
||||
int b2 = static_cast<int>(buffer[m_position + 1]);
|
||||
int b3 = static_cast<int>(buffer[m_position + 2]);
|
||||
int b4 = static_cast<int>(buffer[m_position + 3]);
|
||||
|
||||
m_position += 4;
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
value = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
value = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Absolute get method for reading an int value.
|
||||
// Reads four bytes at the given index, composing them into a int value
|
||||
// according to the current byte order.
|
||||
//
|
||||
// Parameters:
|
||||
// index - The index from which the bytes will be read
|
||||
// Returns:
|
||||
// The int value at the given index
|
||||
int ByteBuffer::getInt(unsigned int index) {
|
||||
assert(index + 3 < m_limit);
|
||||
int value = 0;
|
||||
|
||||
int b1 = static_cast<int>(buffer[index]);
|
||||
int b2 = static_cast<int>(buffer[index + 1]);
|
||||
int b3 = static_cast<int>(buffer[index + 2]);
|
||||
int b4 = static_cast<int>(buffer[index + 3]);
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
value = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
value = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Relative get method for reading a long value.
|
||||
// Reads the next eight bytes at this buffer's current position, composing them
|
||||
// into a long value according to the current byte order, and then increments
|
||||
// the position by eight.
|
||||
//
|
||||
// Returns:
|
||||
// The long value at the buffer's current position
|
||||
int64_t ByteBuffer::getLong() {
|
||||
assert(m_position + 8 < m_limit);
|
||||
|
||||
int64_t value = 0;
|
||||
|
||||
int64_t b1 = static_cast<int64_t>(buffer[m_position]);
|
||||
int64_t b2 = static_cast<int64_t>(buffer[m_position + 1]);
|
||||
int64_t b3 = static_cast<int64_t>(buffer[m_position + 2]);
|
||||
int64_t b4 = static_cast<int64_t>(buffer[m_position + 3]);
|
||||
int64_t b5 = static_cast<int64_t>(buffer[m_position + 4]);
|
||||
int64_t b6 = static_cast<int64_t>(buffer[m_position + 5]);
|
||||
int64_t b7 = static_cast<int64_t>(buffer[m_position + 6]);
|
||||
int64_t b8 = static_cast<int64_t>(buffer[m_position + 7]);
|
||||
|
||||
m_position += 8;
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
value = (b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) | (b5 << 24) |
|
||||
(b6 << 16) | (b7 << 8) | b8;
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
value = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) | (b5 << 32) |
|
||||
(b6 << 40) | (b7 << 48) | (b8 << 56);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Relative get method for reading a short value.
|
||||
// Reads the next two bytes at this buffer's current position, composing them
|
||||
// into a short value according to the current byte order, and then increments
|
||||
// the position by two.
|
||||
//
|
||||
// Returns:
|
||||
// The short value at the buffer's current position
|
||||
short ByteBuffer::getShort() {
|
||||
assert(m_position + 1 < m_limit);
|
||||
|
||||
short value = 0;
|
||||
|
||||
short b1 = static_cast<short>(buffer[m_position]);
|
||||
short b2 = static_cast<short>(buffer[m_position + 1]);
|
||||
|
||||
m_position += 2;
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
value = (b1 << 8) | b2;
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
value = b1 | (b2 << 8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void ByteBuffer::getShortArray(shortArray& s) {
|
||||
// TODO 4J Stu - Should this function be writing from the start of the
|
||||
// buffer, or from position? And should it update position?
|
||||
assert(s.length >= m_limit / 2);
|
||||
|
||||
// 4J Stu - Assumes big endian
|
||||
memcpy(s.data, buffer, (m_limit - m_position));
|
||||
}
|
||||
|
||||
// Absolute put method (optional operation).
|
||||
// Writes the given byte into this buffer at the given index.
|
||||
//
|
||||
// Parameters:
|
||||
// index - The index at which the byte will be written
|
||||
// b - The byte value to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
// Throws:
|
||||
// IndexOutOfBoundsException - If index is negative or not smaller than the
|
||||
// buffer's limit ReadOnlyBufferException - If this buffer is read-only
|
||||
ByteBuffer* ByteBuffer::put(int index, uint8_t b) {
|
||||
assert(index < m_limit);
|
||||
assert(index >= 0);
|
||||
|
||||
buffer[index] = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Relative put method for writing an int value (optional operation).
|
||||
// Writes four bytes containing the given int value, in the current byte order,
|
||||
// into this buffer at the current position, and then increments the position by
|
||||
// four.
|
||||
//
|
||||
// Parameters:
|
||||
// value - The int value to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
ByteBuffer* ByteBuffer::putInt(int value) {
|
||||
assert(m_position + 3 < m_limit);
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
buffer[m_position] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
buffer[m_position + 1] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
buffer[m_position + 2] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[m_position + 3] = static_cast<uint8_t>(value & 0xFF);
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
buffer[m_position] = static_cast<uint8_t>(value & 0xFF);
|
||||
buffer[m_position + 1] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[m_position + 2] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
buffer[m_position + 3] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
m_position += 4;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Absolute put method for writing an int value (optional operation).
|
||||
// Writes four bytes containing the given int value, in the current byte order,
|
||||
// into this buffer at the given index.
|
||||
//
|
||||
// Parameters:
|
||||
// index - The index at which the bytes will be written
|
||||
// value - The int value to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
ByteBuffer* ByteBuffer::putInt(unsigned int index, int value) {
|
||||
assert(index + 3 < m_limit);
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
buffer[index] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
buffer[index + 1] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
buffer[index + 2] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[index + 3] = static_cast<uint8_t>(value & 0xFF);
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
buffer[index] = static_cast<uint8_t>(value & 0xFF);
|
||||
buffer[index + 1] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[index + 2] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
buffer[index + 3] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Relative put method for writing a short value (optional operation).
|
||||
// Writes two bytes containing the given short value, in the current byte order,
|
||||
// into this buffer at the current position, and then increments the position by
|
||||
// two.
|
||||
//
|
||||
// Parameters:
|
||||
// value - The short value to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
ByteBuffer* ByteBuffer::putShort(short value) {
|
||||
assert(m_position + 1 < m_limit);
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
buffer[m_position] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[m_position + 1] = static_cast<uint8_t>(value & 0xFF);
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
buffer[m_position] = static_cast<uint8_t>(value & 0xFF);
|
||||
buffer[m_position + 1] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
m_position += 2;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putShortArray(shortArray& s) {
|
||||
// TODO 4J Stu - Should this function be writing from the start of the
|
||||
// buffer, or from position? And should it update position?
|
||||
assert(s.length * 2 <= m_limit);
|
||||
|
||||
// 4J Stu - Assumes big endian
|
||||
memcpy(buffer, s.data, s.length * 2);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Relative put method for writing a long value (optional operation).
|
||||
// Writes eight bytes containing the given long value, in the current byte
|
||||
// order, into this buffer at the current position, and then increments the
|
||||
// position by eight.
|
||||
//
|
||||
// Parameters:
|
||||
// value - The long value to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
ByteBuffer* ByteBuffer::putLong(int64_t value) {
|
||||
assert(m_position + 7 < m_limit);
|
||||
|
||||
if (byteOrder == BIGENDIAN) {
|
||||
buffer[m_position] = static_cast<uint8_t>((value >> 56) & 0xFF);
|
||||
buffer[m_position + 1] = static_cast<uint8_t>((value >> 48) & 0xFF);
|
||||
buffer[m_position + 2] = static_cast<uint8_t>((value >> 40) & 0xFF);
|
||||
buffer[m_position + 3] = static_cast<uint8_t>((value >> 32) & 0xFF);
|
||||
buffer[m_position + 4] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
buffer[m_position + 5] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
buffer[m_position + 6] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[m_position + 7] = static_cast<uint8_t>(value & 0xFF);
|
||||
} else if (byteOrder == LITTLEENDIAN) {
|
||||
buffer[m_position] = static_cast<uint8_t>((value & 0xFF));
|
||||
buffer[m_position + 1] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
buffer[m_position + 2] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
buffer[m_position + 3] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
buffer[m_position + 4] = static_cast<uint8_t>((value >> 32) & 0xFF);
|
||||
buffer[m_position + 5] = static_cast<uint8_t>((value >> 40) & 0xFF);
|
||||
buffer[m_position + 6] = static_cast<uint8_t>((value >> 48) & 0xFF);
|
||||
buffer[m_position + 7] = static_cast<uint8_t>((value >> 56) & 0xFF);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Relative bulk put method (optional operation).
|
||||
// This method transfers the entire content of the given source byte array into
|
||||
// this buffer. An invocation of this method of the form dst.put(a) behaves in
|
||||
// exactly the same way as the invocation
|
||||
//
|
||||
// dst.put(a, 0, a.length)
|
||||
// Returns:
|
||||
// This buffer
|
||||
ByteBuffer* ByteBuffer::put(byteArray inputArray) {
|
||||
if (inputArray.length > remaining())
|
||||
assert(false); // TODO 4J Stu - Some kind of exception?
|
||||
|
||||
std::copy(inputArray.data, inputArray.data + inputArray.length,
|
||||
buffer + m_position);
|
||||
|
||||
m_position += inputArray.length;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
byteArray ByteBuffer::array() { return byteArray(buffer, m_capacity); }
|
||||
|
||||
// Creates a view of this byte buffer as an int buffer.
|
||||
// The content of the new buffer will start at this buffer's current position.
|
||||
// Changes to this buffer's content will be visible in the new buffer, and vice
|
||||
// versa; the two buffers' position, limit, and mark values will be independent.
|
||||
//
|
||||
// The new buffer's position will be zero, its capacity and its limit will be
|
||||
// the number of bytes remaining in this buffer divided by four, and its mark
|
||||
// will be undefined. The new buffer will be direct if, and only if, this buffer
|
||||
// is direct, and it will be read-only if, and only if, this buffer is
|
||||
// read-only.
|
||||
//
|
||||
// Returns:
|
||||
// A new int buffer
|
||||
IntBuffer* ByteBuffer::asIntBuffer() {
|
||||
// TODO 4J Stu - Is it safe to just cast our byte array pointer to another
|
||||
// type?
|
||||
return new IntBuffer((m_limit - m_position) / 4,
|
||||
(int*)(buffer + m_position));
|
||||
}
|
||||
|
||||
// Creates a view of this byte buffer as a float buffer.
|
||||
// The content of the new buffer will start at this buffer's current position.
|
||||
// Changes to this buffer's content will be visible in the new buffer, and vice
|
||||
// versa; the two buffers' position, limit, and mark values will be independent.
|
||||
//
|
||||
// The new buffer's position will be zero, its capacity and its limit will be
|
||||
// the number of bytes remaining in this buffer divided by four, and its mark
|
||||
// will be undefined. The new buffer will be direct if, and only if, this buffer
|
||||
// is direct, and it will be read-only if, and only if, this buffer is
|
||||
// read-only.
|
||||
//
|
||||
// Returns:
|
||||
// A new float buffer
|
||||
FloatBuffer* ByteBuffer::asFloatBuffer() {
|
||||
// TODO 4J Stu - Is it safe to just cast our byte array pointer to another
|
||||
// type?
|
||||
return new FloatBuffer((m_limit - m_position) / 4,
|
||||
(float*)(buffer + m_position));
|
||||
}
|
||||
4
minecraft/java/src/Class.cpp
Normal file
4
minecraft/java/src/Class.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "Class.h"
|
||||
|
||||
// 4J Stu - To ensure that other classes can get the _class object of it's
|
||||
// superclass, we also need the BaseObject to have that member
|
||||
87
minecraft/java/src/Color.cpp
Normal file
87
minecraft/java/src/Color.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "Color.h"
|
||||
|
||||
// Creates an opaque sRGB color with the specified red, green, and blue values
|
||||
// in the range (0.0 - 1.0). Alpha is defaulted to 1.0. The actual color used in
|
||||
// rendering depends on finding the best match given the color space available
|
||||
// for a particular output device. Parameters: r - the red component g - the
|
||||
// green component b - the blue component Throws: IllegalArgumentException - if
|
||||
// r, g or b are outside of the range 0.0 to 1.0, inclusive
|
||||
Color::Color(float r, float g, float b) {
|
||||
assert(r >= 0.0f && r <= 1.0f);
|
||||
assert(g >= 0.0f && g <= 1.0f);
|
||||
assert(b >= 0.0f && b <= 1.0f);
|
||||
|
||||
// argb
|
||||
colour = ((0xFF << 24) | ((int)(r * 255) << 16) | ((int)(g * 255) << 8) |
|
||||
((int)(b * 255)));
|
||||
}
|
||||
|
||||
Color::Color(int r, int g, int b) {
|
||||
colour =
|
||||
((0xFF << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff)));
|
||||
}
|
||||
|
||||
// Creates a Color object based on the specified values for the HSB color model.
|
||||
// The s and b components should be floating-point values between zero and one
|
||||
// (numbers in the range 0.0-1.0). The h component can be any floating-point
|
||||
// number. The floor of this number is subtracted from it to create a fraction
|
||||
// between 0 and 1. This fractional number is then multiplied by 360 to produce
|
||||
// the hue angle in the HSB color model.
|
||||
//
|
||||
// Parameters:
|
||||
// h - the hue component
|
||||
// s - the saturation of the color
|
||||
// b - the brightness of the color
|
||||
// Returns:
|
||||
// a Color object with the specified hue, saturation, and brightness.
|
||||
Color Color::getHSBColor(float hue, float saturation, float brightness) {
|
||||
int r = 0, g = 0, b = 0;
|
||||
if (saturation == 0) {
|
||||
r = g = b = (int)(brightness * 255.0f + 0.5f);
|
||||
} else {
|
||||
float h = (hue - (float)std::floor(hue)) * 6.0f;
|
||||
float f = h - (float)std::floor(h);
|
||||
float p = brightness * (1.0f - saturation);
|
||||
float q = brightness * (1.0f - saturation * f);
|
||||
float t = brightness * (1.0f - (saturation * (1.0f - f)));
|
||||
switch ((int)h) {
|
||||
case 0:
|
||||
r = (int)(brightness * 255.0f + 0.5f);
|
||||
g = (int)(t * 255.0f + 0.5f);
|
||||
b = (int)(p * 255.0f + 0.5f);
|
||||
break;
|
||||
case 1:
|
||||
r = (int)(q * 255.0f + 0.5f);
|
||||
g = (int)(brightness * 255.0f + 0.5f);
|
||||
b = (int)(p * 255.0f + 0.5f);
|
||||
break;
|
||||
case 2:
|
||||
r = (int)(p * 255.0f + 0.5f);
|
||||
g = (int)(brightness * 255.0f + 0.5f);
|
||||
b = (int)(t * 255.0f + 0.5f);
|
||||
break;
|
||||
case 3:
|
||||
r = (int)(p * 255.0f + 0.5f);
|
||||
g = (int)(q * 255.0f + 0.5f);
|
||||
b = (int)(brightness * 255.0f + 0.5f);
|
||||
break;
|
||||
case 4:
|
||||
r = (int)(t * 255.0f + 0.5f);
|
||||
g = (int)(p * 255.0f + 0.5f);
|
||||
b = (int)(brightness * 255.0f + 0.5f);
|
||||
break;
|
||||
case 5:
|
||||
r = (int)(brightness * 255.0f + 0.5f);
|
||||
g = (int)(p * 255.0f + 0.5f);
|
||||
b = (int)(q * 255.0f + 0.5f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Color(r, g, b);
|
||||
}
|
||||
|
||||
int Color::getRGB() { return colour; }
|
||||
400
minecraft/java/src/File.cpp
Normal file
400
minecraft/java/src/File.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
#include "FileFilter.h"
|
||||
#include "File.h"
|
||||
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/PathHelper.h" // 4jcraft TODO
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/StringHelpers.h" // 4jcraft TODO
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
|
||||
const wchar_t File::pathSeparator = L'/';
|
||||
|
||||
const std::wstring File::pathRoot =
|
||||
L""; // Path root after pathSeparator has been removed
|
||||
|
||||
namespace {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
fs::path ToFilesystemPath(const std::wstring& path) {
|
||||
const std::string nativePath = wstringtofilename(path);
|
||||
return fs::path(nativePath);
|
||||
}
|
||||
|
||||
std::wstring ToFilename(const fs::path& path) {
|
||||
const std::string filename = path.filename().string();
|
||||
return filenametowstring(filename.c_str());
|
||||
}
|
||||
|
||||
int64_t ToEpochMilliseconds(const fs::file_time_type& fileTime) {
|
||||
using namespace std::chrono;
|
||||
|
||||
const auto systemTime = time_point_cast<milliseconds>(
|
||||
fileTime - fs::file_time_type::clock::now() + system_clock::now());
|
||||
return static_cast<int64_t>(systemTime.time_since_epoch().count());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Creates a new File instance from a parent abstract pathname and a child
|
||||
// pathname string.
|
||||
File::File(const File& parent, const std::wstring& child) {
|
||||
m_abstractPathName = parent.getPath() + pathSeparator + child;
|
||||
}
|
||||
|
||||
// Creates a new File instance by converting the given pathname string into an
|
||||
// abstract pathname.
|
||||
|
||||
File::File(const std::wstring& pathname) {
|
||||
if (pathname.empty()) {
|
||||
m_abstractPathName = L"";
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring fixedPath = pathname;
|
||||
for (size_t i = 0; i < fixedPath.length(); ++i) {
|
||||
if (fixedPath[i] == L'\\') fixedPath[i] = L'/';
|
||||
}
|
||||
size_t dpos;
|
||||
while ((dpos = fixedPath.find(L"//")) != std::wstring::npos)
|
||||
fixedPath.erase(dpos, 1);
|
||||
if (fixedPath.find(L"GAME:/") == 0) fixedPath = fixedPath.substr(6);
|
||||
m_abstractPathName = fixedPath;
|
||||
|
||||
#if defined(__linux__)
|
||||
std::string request = wstringtofilename(m_abstractPathName);
|
||||
while (!request.empty() && request[0] == '/') request.erase(0, 1);
|
||||
if (request.find("res/") == 0) request.erase(0, 4);
|
||||
|
||||
std::string exeDir = PathHelper::GetExecutableDirA();
|
||||
std::string fileName = request;
|
||||
size_t lastSlash = fileName.find_last_of('/');
|
||||
if (lastSlash != std::string::npos)
|
||||
fileName = fileName.substr(lastSlash + 1);
|
||||
|
||||
const char* bases[] = {"/",
|
||||
"/Common/res/TitleUpdate/res/",
|
||||
"/Common/Media/",
|
||||
"/Common/res/",
|
||||
"/Common/",
|
||||
"Minecraft.Assets/"};
|
||||
|
||||
for (const char* base : bases) {
|
||||
std::string tryFull = exeDir + base + request;
|
||||
std::string tryFile = exeDir + base + fileName;
|
||||
if (access(tryFull.c_str(), F_OK) != -1) {
|
||||
m_abstractPathName = convStringToWstring(tryFull);
|
||||
return;
|
||||
}
|
||||
if (access(tryFile.c_str(), F_OK) != -1) {
|
||||
m_abstractPathName = convStringToWstring(tryFile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
std::string path = wstringtofilename(m_abstractPathName);
|
||||
std::string finalPath = StorageManager.GetMountedPath(path.c_str());
|
||||
if (finalPath.size() == 0) finalPath = path;
|
||||
m_abstractPathName = convStringToWstring(finalPath);
|
||||
#endif
|
||||
/*
|
||||
std::vector<std::wstring> path = stringSplit( pathname, pathSeparator );
|
||||
|
||||
if( path.back().compare( pathRoot ) != 0 )
|
||||
m_abstractPathName = path.back();
|
||||
else
|
||||
m_abstractPathName = L"";
|
||||
|
||||
path.pop_back();
|
||||
|
||||
if( path.size() > 0 )
|
||||
{
|
||||
// If the last member of the vector is the root then just stop
|
||||
if( path.back().compare( pathRoot ) != 0 )
|
||||
this->parent = new File( &path );
|
||||
else
|
||||
this->parent = nullptr;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
File::File(const std::wstring& parent,
|
||||
const std::wstring& child) //: m_abstractPathName( child )
|
||||
{
|
||||
m_abstractPathName =
|
||||
pathRoot + pathSeparator + parent + pathSeparator + child;
|
||||
// this->parent = new File( parent );
|
||||
}
|
||||
|
||||
// Creates a new File instance by converting the given path vector into an
|
||||
// abstract pathname.
|
||||
/*
|
||||
File::File( std::vector<std::wstring> *path ) : parent( nullptr )
|
||||
{
|
||||
m_abstractPathName = path->back();
|
||||
path->pop_back();
|
||||
|
||||
if( path->size() > 0 )
|
||||
{
|
||||
// If the last member of the vector is the root then just stop
|
||||
if( path->back().compare( pathRoot ) != 0 )
|
||||
this->parent = new File( path );
|
||||
else
|
||||
this->parent = nullptr;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Deletes the file or directory denoted by this abstract pathname. If this
|
||||
// pathname denotes a directory, then the directory must be empty in order to be
|
||||
// deleted. Returns: true if and only if the file or directory is successfully
|
||||
// deleted; false otherwise
|
||||
bool File::_delete() {
|
||||
std::error_code error;
|
||||
const bool result = fs::remove(ToFilesystemPath(getPath()), error);
|
||||
if (!result || error) {
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
printf("File::_delete - Error code %d (%#0.8X)\n", error.value(),
|
||||
error.value());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates the directory named by this abstract pathname.
|
||||
// Returns:
|
||||
// true if and only if the directory was created; false otherwise
|
||||
bool File::mkdir() const {
|
||||
std::error_code error;
|
||||
return fs::create_directory(ToFilesystemPath(getPath()), error);
|
||||
}
|
||||
|
||||
// Creates the directory named by this abstract pathname, including any
|
||||
// necessary but nonexistent parent directories. Note that if this
|
||||
// operation fails it may have succeeded in creating some of the necessary
|
||||
// parent directories.
|
||||
//
|
||||
//@return <code>true</code> if and only if the directory was created,
|
||||
// along with all necessary parent directories; <code>false</code>
|
||||
// otherwise
|
||||
//
|
||||
//@throws SecurityException
|
||||
// If a security manager exists and its <code>{@link
|
||||
// java.lang.SecurityManager#checkRead(java.lang.String)}</code>
|
||||
// method does not permit verification of the existence of the
|
||||
// named directory and all necessary parent directories; or if
|
||||
// the <code>{@link
|
||||
// java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
|
||||
// method does not permit the named directory and all necessary
|
||||
// parent directories to be created
|
||||
//
|
||||
bool File::mkdirs() const {
|
||||
std::error_code error;
|
||||
const fs::path path = ToFilesystemPath(getPath());
|
||||
|
||||
if (fs::exists(path, error)) {
|
||||
return fs::is_directory(path, error);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fs::create_directories(path, error);
|
||||
}
|
||||
|
||||
/*
|
||||
File *File::getParent() const
|
||||
{
|
||||
return (File *) parent;
|
||||
}
|
||||
*/
|
||||
|
||||
// Tests whether the file or directory denoted by this abstract pathname exists.
|
||||
// Returns:
|
||||
// true if and only if the file or directory denoted by this abstract pathname
|
||||
// exists; false otherwise
|
||||
bool File::exists() const {
|
||||
// TODO 4J Stu - Possible we could get an error result from something other
|
||||
// than the file not existing?
|
||||
std::error_code error;
|
||||
return fs::exists(ToFilesystemPath(getPath()), error);
|
||||
}
|
||||
|
||||
// Tests whether the file denoted by this abstract pathname is a normal file. A
|
||||
// file is normal if it is not a directory and, in addition, satisfies other
|
||||
// system-dependent criteria. Any non-directory file created by a Java
|
||||
// application is guaranteed to be a normal file. Returns: true if and only if
|
||||
// the file denoted by this abstract pathname exists and is a normal file; false
|
||||
// otherwise
|
||||
bool File::isFile() const { return exists() && !isDirectory(); }
|
||||
|
||||
// Renames the file denoted by this abstract pathname.
|
||||
// Whether or not this method can move a file from one filesystem to another is
|
||||
// platform-dependent. The return value should always be checked to make sure
|
||||
// that the rename operation was successful.
|
||||
//
|
||||
// Parameters:
|
||||
// dest - The new abstract pathname for the named file
|
||||
// Returns:
|
||||
// true if and only if the renaming succeeded; false otherwise
|
||||
bool File::renameTo(File dest) {
|
||||
std::error_code error;
|
||||
fs::rename(ToFilesystemPath(getPath()), ToFilesystemPath(dest.getPath()),
|
||||
error);
|
||||
if (error) {
|
||||
perror("File::renameTo - Error renaming file");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns an array of abstract pathnames denoting the files in the directory
|
||||
// denoted by this abstract pathname. If this abstract pathname does not denote
|
||||
// a directory, then this method returns null. Otherwise an array of File
|
||||
// objects is returned, one for each file or directory in the directory.
|
||||
// Pathnames denoting the directory itself and the directory's parent directory
|
||||
// are not included in the result. Each resulting abstract pathname is
|
||||
// constructed from this abstract pathname using the File(File, String)
|
||||
// constructor. Therefore if this pathname is absolute then each resulting
|
||||
// pathname is absolute; if this pathname is relative then each resulting
|
||||
// pathname will be relative to the same directory.
|
||||
//
|
||||
// There is no guarantee that the name strings in the resulting array will
|
||||
// appear in any specific order; they are not, in particular, guaranteed to
|
||||
// appear in alphabetical order.
|
||||
//
|
||||
// Returns:
|
||||
// An array of abstract pathnames denoting the files and directories in the
|
||||
// directory denoted by this abstract pathname. The array will be empty if the
|
||||
// directory is empty. Returns null if this abstract pathname does not denote a
|
||||
// directory, or if an I/O error occurs.
|
||||
std::vector<File*>* File::listFiles() const {
|
||||
std::vector<File*>* vOutput = new std::vector<File*>();
|
||||
|
||||
// TODO 4J Stu - Also need to check for I/O errors?
|
||||
if (!isDirectory()) return vOutput;
|
||||
|
||||
std::error_code error;
|
||||
for (fs::directory_iterator it(ToFilesystemPath(getPath()), error);
|
||||
!error && it != fs::directory_iterator(); it.increment(error)) {
|
||||
vOutput->push_back(new File(*this, ToFilename(it->path())));
|
||||
}
|
||||
return vOutput;
|
||||
}
|
||||
|
||||
// Returns an array of abstract pathnames denoting the files and directories in
|
||||
// the directory denoted by this abstract pathname that satisfy the specified
|
||||
// filter. The behavior of this method is the same as that of the listFiles()
|
||||
// method, except that the pathnames in the returned array must satisfy the
|
||||
// filter. If the given filter is null then all pathnames are accepted.
|
||||
// Otherwise, a pathname satisfies the filter if and only if the value true
|
||||
// results when the FileFilter.accept(java.io.File) method of the filter is
|
||||
// invoked on the pathname. Parameters: filter - A file filter Returns: An array
|
||||
// of abstract pathnames denoting the files and directories in the directory
|
||||
// denoted by this abstract pathname. The array will be empty if the directory
|
||||
// is empty. Returns null if this abstract pathname does not denote a directory,
|
||||
// or if an I/O error occurs.
|
||||
std::vector<File*>* File::listFiles(FileFilter* filter) const {
|
||||
// TODO 4J Stu - Also need to check for I/O errors?
|
||||
if (!isDirectory()) return nullptr;
|
||||
|
||||
std::vector<File*>* vOutput = new std::vector<File*>();
|
||||
|
||||
std::error_code error;
|
||||
for (fs::directory_iterator it(ToFilesystemPath(getPath()), error);
|
||||
!error && it != fs::directory_iterator(); it.increment(error)) {
|
||||
File thisFile = File(*this, ToFilename(it->path()));
|
||||
if (filter->accept(&thisFile)) {
|
||||
vOutput->push_back(new File(thisFile));
|
||||
}
|
||||
}
|
||||
return vOutput;
|
||||
}
|
||||
|
||||
// Tests whether the file denoted by this abstract pathname is a directory.
|
||||
// Returns:
|
||||
// true if and only if the file denoted by this abstract pathname exists and is
|
||||
// a directory; false otherwise
|
||||
bool File::isDirectory() const {
|
||||
std::error_code error;
|
||||
return fs::is_directory(ToFilesystemPath(getPath()), error);
|
||||
}
|
||||
|
||||
// Returns the length of the file denoted by this abstract pathname. The return
|
||||
// value is unspecified if this pathname denotes a directory. Returns: The
|
||||
// length, in bytes, of the file denoted by this abstract pathname, or 0L if the
|
||||
// file does not exist
|
||||
int64_t File::length() {
|
||||
std::error_code error;
|
||||
const fs::path path = ToFilesystemPath(getPath());
|
||||
|
||||
if (fs::is_regular_file(path, error)) {
|
||||
const auto size = fs::file_size(path, error);
|
||||
if (!error) {
|
||||
return static_cast<int64_t>(size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the time that the file denoted by this abstract pathname was last
|
||||
// modified. Returns: A long value representing the time the file was last
|
||||
// modified, measured in milliseconds since the epoch (00:00:00 GMT, January 1,
|
||||
// 1970), or 0L if the file does not exist or if an I/O error occurs
|
||||
int64_t File::lastModified() {
|
||||
std::error_code error;
|
||||
const fs::path path = ToFilesystemPath(getPath());
|
||||
|
||||
if (fs::is_regular_file(path, error)) {
|
||||
const fs::file_time_type lastWriteTime =
|
||||
fs::last_write_time(path, error);
|
||||
if (!error) {
|
||||
return ToEpochMilliseconds(lastWriteTime);
|
||||
}
|
||||
}
|
||||
|
||||
return 0l;
|
||||
}
|
||||
|
||||
const std::wstring File::getPath() const {
|
||||
/*
|
||||
std::wstring path;
|
||||
if ( parent != nullptr)
|
||||
path = parent->getPath();
|
||||
else
|
||||
path = std::wstring(pathRoot);
|
||||
|
||||
path.push_back( pathSeparator );
|
||||
path.append(m_abstractPathName);
|
||||
*/
|
||||
return m_abstractPathName;
|
||||
}
|
||||
|
||||
std::wstring File::getName() const {
|
||||
unsigned int sep =
|
||||
(unsigned int)(m_abstractPathName.find_last_of(this->pathSeparator));
|
||||
return m_abstractPathName.substr(sep + 1, m_abstractPathName.length());
|
||||
}
|
||||
|
||||
bool File::eq_test(const File& x, const File& y) {
|
||||
return x.getPath().compare(y.getPath()) == 0;
|
||||
}
|
||||
|
||||
// 4J TODO JEV, a better hash function may be nessesary.
|
||||
int File::hash_fnct(const File& k) {
|
||||
int hashCode = 0;
|
||||
|
||||
// if (k->parent != nullptr)
|
||||
// hashCode = hash_fnct(k->getParent());
|
||||
|
||||
wchar_t* ref = (wchar_t*)k.m_abstractPathName.c_str();
|
||||
|
||||
for (unsigned int i = 0; i < k.m_abstractPathName.length(); i++) {
|
||||
hashCode += ((hashCode * 33) + ref[i]) % 149;
|
||||
}
|
||||
|
||||
return (int)hashCode;
|
||||
}
|
||||
61
minecraft/java/src/FloatBuffer.cpp
Normal file
61
minecraft/java/src/FloatBuffer.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "FloatBuffer.h"
|
||||
|
||||
// Allocates a new float buffer.
|
||||
// The new buffer's position will be zero, its limit will be its capacity, and
|
||||
// its mark will be undefined. It will have a backing array, and its array
|
||||
// offset will be zero.
|
||||
//
|
||||
// Parameters:
|
||||
// capacity - The new buffer's capacity, in floats
|
||||
FloatBuffer::FloatBuffer(unsigned int capacity) : Buffer(capacity) {
|
||||
buffer = new float[capacity];
|
||||
memset(buffer, 0, sizeof(float) * capacity);
|
||||
}
|
||||
|
||||
FloatBuffer::FloatBuffer(unsigned int capacity, float* backingArray)
|
||||
: Buffer(capacity) {
|
||||
hasBackingArray = true;
|
||||
buffer = backingArray;
|
||||
}
|
||||
|
||||
FloatBuffer::~FloatBuffer() {
|
||||
if (!hasBackingArray) delete[] buffer;
|
||||
}
|
||||
|
||||
// Flips this buffer. The limit is set to the current position and then the
|
||||
// position is set to zero. If the mark is defined then it is discarded.
|
||||
//
|
||||
// Returns:
|
||||
// This buffer
|
||||
FloatBuffer* FloatBuffer::flip() {
|
||||
m_limit = m_position;
|
||||
m_position = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Relative put method (optional operation).
|
||||
// Writes the given float into this buffer at the current position, and then
|
||||
// increments the position.
|
||||
//
|
||||
// Parameters:
|
||||
// f - The float to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
FloatBuffer* FloatBuffer::put(float f) {
|
||||
buffer[m_position++] = f;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Relative bulk get method.
|
||||
// This method transfers floats from this buffer into the given destination
|
||||
// array. An invocation of this method of the form src.get(a) behaves in exactly
|
||||
// the same way as the invocation
|
||||
//
|
||||
// src.get(a, 0, a.length)
|
||||
// Returns:
|
||||
// This buffer
|
||||
void FloatBuffer::get(floatArray* dst) {
|
||||
assert(dst->length <= m_capacity);
|
||||
|
||||
for (unsigned int i = 0; i < dst->length; i++) dst->data[i] = buffer[i];
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#include "InputOutputStream/BufferedOutputStream.h"
|
||||
|
||||
// Creates a new buffered output stream to write data to the specified
|
||||
// underlying output stream with the specified buffer size. Parameters: out -
|
||||
// the underlying output stream. size - the buffer size.
|
||||
BufferedOutputStream::BufferedOutputStream(OutputStream* out, int size) {
|
||||
stream = out;
|
||||
buf = byteArray(size);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
BufferedOutputStream::~BufferedOutputStream() {
|
||||
// 4jcraft, changed to [], deallocates internal buffer
|
||||
// TODO: ArrayWithLength.h doesnt have a destructor.
|
||||
// this wouldnt need to be done manually.
|
||||
// but for some reason the destructor is commented out in the source code?
|
||||
delete[] buf.data;
|
||||
}
|
||||
|
||||
// Flushes this buffered output stream. This forces any buffered output bytes to
|
||||
// be written out to the underlying output stream.
|
||||
void BufferedOutputStream::flush() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"BufferedOutputStream::flush() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
stream->write(buf, 0, count);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Closes this output stream and releases any system resources associated with
|
||||
// the stream. The close method of FilterOutputStream calls its flush method,
|
||||
// and then calls the close method of its underlying output stream.
|
||||
void BufferedOutputStream::close() {
|
||||
flush();
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"BufferedOutputStream::close() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->close();
|
||||
}
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to this
|
||||
// buffered output stream. Ordinarily this method stores bytes from the given
|
||||
// array into this stream's buffer, flushing the buffer to the underlying output
|
||||
// stream as needed. If the requested length is at least as large as this
|
||||
// stream's buffer, however, then this method will flush the buffer and write
|
||||
// the bytes directly to the underlying output stream. Thus redundant
|
||||
// BufferedOutputStreams will not copy data unnecessarily.
|
||||
//
|
||||
// Overrides:
|
||||
// write in class FilterOutputStream
|
||||
// Parameters:
|
||||
// b - the data.
|
||||
// off - the start offset in the data.
|
||||
// len - the number of bytes to write.
|
||||
void BufferedOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
// Over the length of what we can store in our buffer - just flush the
|
||||
// buffer and output directly
|
||||
if (length >= buf.length) {
|
||||
flush();
|
||||
stream->write(b, offset, length);
|
||||
} else {
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
write(static_cast<unsigned int>(b[offset + i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Writes b.length bytes to this output stream.
|
||||
// The write method of FilterOutputStream calls its write method of three
|
||||
// arguments with the arguments b, 0, and b.length.
|
||||
//
|
||||
// Note that this method does not call the one-argument write method of its
|
||||
// underlying stream with the single argument b.
|
||||
void BufferedOutputStream::write(byteArray b) { write(b, 0, b.length); }
|
||||
|
||||
// Writes the specified byte to this buffered output stream.
|
||||
// Overrides:
|
||||
// write in class FilterOutputStream
|
||||
// Parameters:
|
||||
// b - the byte to be written.
|
||||
void BufferedOutputStream::write(unsigned int b) {
|
||||
buf[count++] = (uint8_t)b;
|
||||
if (count == buf.length) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
158
minecraft/java/src/InputOutputStream/BufferedReader.cpp
Normal file
158
minecraft/java/src/InputOutputStream/BufferedReader.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "InputOutputStream/BufferedReader.h"
|
||||
|
||||
// Creates a buffering character-input stream that uses a default-sized input
|
||||
// buffer. Parameters: in - A Reader
|
||||
BufferedReader::BufferedReader(Reader* in)
|
||||
: reader(in), readMark(0), bufferedMark(0), eofReached(false) {
|
||||
bufferSize = 64;
|
||||
buffer = new wchar_t[bufferSize];
|
||||
memset(buffer, 0, sizeof(wchar_t) * bufferSize);
|
||||
bufferMore();
|
||||
}
|
||||
|
||||
BufferedReader::~BufferedReader() { delete[] buffer; }
|
||||
|
||||
void BufferedReader::bufferMore() {
|
||||
// Don't buffer more unless we are going to read at least twice as much as
|
||||
// what is already left
|
||||
if (bufferedMark - readMark > (BUFFER_MORE_AMOUNT / 2)) return;
|
||||
|
||||
if (bufferSize < (bufferedMark + BUFFER_MORE_AMOUNT)) {
|
||||
// Enlarge the buffer
|
||||
wchar_t* temp = new wchar_t[bufferSize * 2];
|
||||
memset(temp, 0, sizeof(wchar_t) * bufferSize * 2);
|
||||
std::copy(buffer, buffer + bufferSize, temp);
|
||||
|
||||
delete[] buffer;
|
||||
buffer = temp;
|
||||
bufferSize = bufferSize * 2;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
unsigned int newCharsBuffered = 0;
|
||||
while (newCharsBuffered < BUFFER_MORE_AMOUNT &&
|
||||
(value = reader->read()) != -1) {
|
||||
buffer[bufferedMark++] = value;
|
||||
newCharsBuffered++;
|
||||
}
|
||||
}
|
||||
|
||||
// Closes the stream and releases any system resources associated with it. Once
|
||||
// the stream has been closed, further read(), ready(), mark(), reset(), or
|
||||
// skip() invocations will throw an IOException. Closing a previously closed
|
||||
// stream has no effect.
|
||||
void BufferedReader::close() { reader->close(); }
|
||||
|
||||
// Reads a single character.
|
||||
// Returns:
|
||||
// The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or
|
||||
// -1 if the end of the stream has been reached
|
||||
int BufferedReader::read() {
|
||||
// We should have buffered at least as much as we have read
|
||||
assert(bufferedMark >= readMark);
|
||||
|
||||
if (bufferedMark == readMark) {
|
||||
int value = reader->read();
|
||||
if (value == -1) return -1;
|
||||
|
||||
buffer[bufferedMark++] = value;
|
||||
|
||||
bufferMore();
|
||||
}
|
||||
|
||||
return buffer[readMark++];
|
||||
}
|
||||
|
||||
// Reads characters into a portion of an array.
|
||||
// This method implements the general contract of the corresponding read method
|
||||
// of the Reader class. As an additional convenience, it attempts to read as
|
||||
// many characters as possible by repeatedly invoking the read method of the
|
||||
// underlying stream. This iterated read continues until one of the following
|
||||
// conditions becomes true:
|
||||
//
|
||||
// The specified number of characters have been read,
|
||||
// The read method of the underlying stream returns -1, indicating end-of-file,
|
||||
// or The ready method of the underlying stream returns false, indicating that
|
||||
// further input requests would block. If the first read on the underlying
|
||||
// stream returns -1 to indicate end-of-file then this method returns -1.
|
||||
// Otherwise this method returns the number of characters actually read.
|
||||
// Subclasses of this class are encouraged, but not required, to attempt to read
|
||||
// as many characters as possible in the same fashion.
|
||||
//
|
||||
// Ordinarily this method takes characters from this stream's character buffer,
|
||||
// filling it from the underlying stream as necessary. If, however, the buffer
|
||||
// is empty, the mark is not valid, and the requested length is at least as
|
||||
// large as the buffer, then this method will read characters directly from the
|
||||
// underlying stream into the given array. Thus redundant BufferedReaders will
|
||||
// not copy data unnecessarily.
|
||||
//
|
||||
// Parameters:
|
||||
// cbuf - Destination buffer
|
||||
// off - Offset at which to start storing characters
|
||||
// len - Maximum number of characters to read
|
||||
// Returns:
|
||||
// The number of characters read, or -1 if the end of the stream has been
|
||||
// reached
|
||||
int BufferedReader::read(wchar_t cbuf[], unsigned int off, unsigned int len) {
|
||||
if (bufferSize < (bufferedMark + len)) {
|
||||
// Enlarge the buffer
|
||||
wchar_t* temp = new wchar_t[bufferSize * 2];
|
||||
memset(temp, 0, sizeof(wchar_t) * bufferSize * 2);
|
||||
std::copy(buffer, buffer + bufferSize, temp);
|
||||
|
||||
delete[] buffer;
|
||||
buffer = temp;
|
||||
bufferSize = bufferSize * 2;
|
||||
}
|
||||
|
||||
unsigned int charsRead = 0;
|
||||
while (charsRead < len && readMark <= bufferedMark) {
|
||||
cbuf[off + charsRead] = buffer[readMark++];
|
||||
charsRead++;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
while (charsRead < len && (value = reader->read()) != -1) {
|
||||
buffer[bufferedMark++] = value;
|
||||
cbuf[off + charsRead] = value;
|
||||
charsRead++;
|
||||
readMark++;
|
||||
}
|
||||
|
||||
bufferMore();
|
||||
|
||||
return charsRead;
|
||||
}
|
||||
|
||||
// Reads a line of text. A line is considered to be terminated by any one of a
|
||||
// line feed ('\n'), a carriage return ('\r'), or a carriage return followed
|
||||
// immediately by a linefeed. Returns: A String containing the contents of the
|
||||
// line, not including any line-termination characters, or null if the end of
|
||||
// the stream has been reached
|
||||
std::wstring BufferedReader::readLine() {
|
||||
std::wstring output = L"";
|
||||
bool newLineCharFound = false;
|
||||
|
||||
while (readMark < bufferedMark) {
|
||||
wchar_t value = buffer[readMark++];
|
||||
|
||||
if (!newLineCharFound) {
|
||||
if ((value == '\n') || (value == '\r')) {
|
||||
newLineCharFound = true;
|
||||
} else {
|
||||
output.push_back(value);
|
||||
}
|
||||
} else {
|
||||
if ((value != '\n') && (value != '\r')) {
|
||||
readMark--; // Move back the read mark on char so we get this
|
||||
// char again next time
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This will only actually read more from the stream if we have less
|
||||
// than half of the amount that will be added left to read
|
||||
bufferMore();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
109
minecraft/java/src/InputOutputStream/ByteArrayInputStream.cpp
Normal file
109
minecraft/java/src/InputOutputStream/ByteArrayInputStream.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "InputOutputStream/InputOutputStream.h"
|
||||
|
||||
// Creates ByteArrayInputStream that uses buf as its buffer array. The initial
|
||||
// value of pos is offset and the initial value of count is the minimum of
|
||||
// offset+length and buf.length. The buffer array is not copied. The buffer's
|
||||
// mark is set to the specified offset. Parameters: buf - the input buffer.
|
||||
// offset - the offset in the buffer of the first byte to read.
|
||||
// length - the maximum number of bytes to read from the buffer.
|
||||
ByteArrayInputStream::ByteArrayInputStream(byteArray buf, unsigned int offset,
|
||||
unsigned int length)
|
||||
: pos(offset), count(std::min(offset + length, buf.length)), mark(offset) {
|
||||
this->buf = buf;
|
||||
}
|
||||
|
||||
// Creates a ByteArrayInputStream so that it uses buf as its buffer array. The
|
||||
// buffer array is not copied. The initial value of pos is 0 and the initial
|
||||
// value of count is the length of buf. Parameters: buf - the input buffer.
|
||||
ByteArrayInputStream::ByteArrayInputStream(byteArray buf)
|
||||
: pos(0), count(buf.length), mark(0) {
|
||||
this->buf = buf;
|
||||
}
|
||||
|
||||
// Reads the next byte of data from this input stream. The value byte is
|
||||
// returned as an int in the range 0 to 255. If no byte is available because the
|
||||
// end of the stream has been reached, the value -1 is returned. This read
|
||||
// method cannot block. Returns: the next byte of data, or -1 if the end of the
|
||||
// stream has been reached.
|
||||
int ByteArrayInputStream::read() {
|
||||
if (pos >= count)
|
||||
return -1;
|
||||
else
|
||||
return static_cast<unsigned int>(buf[pos++]);
|
||||
}
|
||||
|
||||
// Reads some number of bytes from the input stream and stores them into the
|
||||
// buffer array b. The number of bytes actually read is returned as an integer.
|
||||
// This method blocks until input data is available, end of file is detected, or
|
||||
// an exception is thrown. If the length of b is zero, then no bytes are read
|
||||
// and 0 is returned; otherwise, there is an attempt to read at least one byte.
|
||||
// If no byte is available because the stream is at the end of the file, the
|
||||
// value -1 is returned; otherwise, at least one byte is read and stored into b.
|
||||
//
|
||||
// The first byte read is stored into element b[0], the next one into b[1], and
|
||||
// so on. The number of bytes read is, at most, equal to the length of b. Let k
|
||||
// be the number of bytes actually read; these bytes will be stored in elements
|
||||
// b[0] through b[k-1], leaving elements b[k] through b[b.length-1] unaffected.
|
||||
//
|
||||
// The read(b) method for class InputStream has the same effect as:
|
||||
//
|
||||
// read(b, 0, b.length)
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 is there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int ByteArrayInputStream::read(byteArray b) { return read(b, 0, b.length); }
|
||||
|
||||
// Reads up to len bytes of data into an array of bytes from this input stream.
|
||||
// If pos equals count, then -1 is returned to indicate end of file. Otherwise,
|
||||
// the number k of bytes read is equal to the smaller of len and count-pos. If k
|
||||
// is positive, then bytes buf[pos] through buf[pos+k-1] are copied into b[off]
|
||||
// through b[off+k-1] in the manner performed by System.arraycopy. The value k
|
||||
// is added into pos and k is returned. This read method cannot block.
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// off - the start offset in the destination array b
|
||||
// len - the maximum number of bytes read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 if there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int ByteArrayInputStream::read(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
if (pos == count) return -1;
|
||||
|
||||
int k = std::min(length, count - pos);
|
||||
std::memcpy(&b[offset], &buf[pos], k);
|
||||
// std::copy( buf->data+pos, buf->data+pos+k, b->data + offset ); // Or this
|
||||
// instead?
|
||||
|
||||
pos += k;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
// Closing a ByteArrayInputStream has no effect.
|
||||
// The methods in this class can be called after the stream has been closed
|
||||
// without generating an IOException.
|
||||
void ByteArrayInputStream::close() { return; }
|
||||
|
||||
// Skips n bytes of input from this input stream. Fewer bytes might be skipped
|
||||
// if the end of the input stream is reached. The actual number k of bytes to be
|
||||
// skipped is equal to the smaller of n and count-pos. The value k is added into
|
||||
// pos and k is returned. Overrides: skip in class InputStream Parameters: n -
|
||||
// the number of bytes to be skipped. Returns: the actual number of bytes
|
||||
// skipped.
|
||||
int64_t ByteArrayInputStream::skip(int64_t n) {
|
||||
int newPos = pos + n;
|
||||
|
||||
if (newPos > count) newPos = count;
|
||||
|
||||
int k = newPos - pos;
|
||||
pos = newPos;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
ByteArrayInputStream::~ByteArrayInputStream() {
|
||||
if (buf.data != nullptr) delete[] buf.data;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "InputOutputStream/ByteArrayOutputStream.h"
|
||||
|
||||
// Creates a new byte array output stream. The buffer capacity is initially 32
|
||||
// bytes, though its size increases if necessary.
|
||||
ByteArrayOutputStream::ByteArrayOutputStream() {
|
||||
count = 0;
|
||||
buf = byteArray(32);
|
||||
}
|
||||
|
||||
// Creates a new byte array output stream, with a buffer capacity of the
|
||||
// specified size, in bytes. Parameters: size - the initial size.
|
||||
ByteArrayOutputStream::ByteArrayOutputStream(unsigned int size) {
|
||||
count = 0;
|
||||
buf = byteArray(size);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream::~ByteArrayOutputStream() {
|
||||
if (buf.data != nullptr) delete[] buf.data;
|
||||
}
|
||||
|
||||
// Writes the specified byte to this byte array output stream.
|
||||
// Parameters:
|
||||
// b - the byte to be written.
|
||||
void ByteArrayOutputStream::write(unsigned int b) {
|
||||
// If we will fill the buffer we need to make it bigger
|
||||
if (count + 1 >= buf.length) buf.resize(buf.length * 2);
|
||||
|
||||
buf[count] = (uint8_t)b;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Writes b.length bytes from the specified byte array to this output stream.
|
||||
// The general contract for write(b) is that it should have exactly the same
|
||||
// effect as the call write(b, 0, b.length).
|
||||
void ByteArrayOutputStream::write(byteArray b) { write(b, 0, b.length); }
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to this
|
||||
// byte array output stream. Parameters: b - the data. off - the start offset in
|
||||
// the data. len - the number of bytes to write.
|
||||
void ByteArrayOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
assert(b.length >= offset + length);
|
||||
|
||||
// If we will fill the buffer we need to make it bigger
|
||||
if (count + length >= buf.length)
|
||||
buf.resize(std::max(count + length + 1, buf.length * 2));
|
||||
|
||||
std::memcpy(&buf[count], &b[offset], length);
|
||||
// std::copy( b->data+offset, b->data+offset+length, buf->data + count ); //
|
||||
// Or this instead?
|
||||
|
||||
count += length;
|
||||
}
|
||||
|
||||
// Closing a ByteArrayOutputStream has no effect.
|
||||
// The methods in this class can be called after the stream has been closed
|
||||
// without generating an IOException.
|
||||
void ByteArrayOutputStream::close() {}
|
||||
|
||||
// Creates a newly allocated byte array. Its size is the current size of this
|
||||
// output stream and the valid contents of the buffer have been copied into it.
|
||||
// Returns:
|
||||
// the current contents of this output stream, as a byte array.
|
||||
byteArray ByteArrayOutputStream::toByteArray() {
|
||||
byteArray out(count);
|
||||
memcpy(out.data, buf.data, count);
|
||||
return out;
|
||||
}
|
||||
609
minecraft/java/src/InputOutputStream/DataInputStream.cpp
Normal file
609
minecraft/java/src/InputOutputStream/DataInputStream.cpp
Normal file
@@ -0,0 +1,609 @@
|
||||
#include "InputOutputStream/DataInputStream.h"
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
// Creates a DataInputStream that uses the specified underlying InputStream.
|
||||
// Parameters:
|
||||
// in - the specified input stream
|
||||
DataInputStream::DataInputStream(InputStream* in) : stream(in) {}
|
||||
|
||||
// Reads the next byte of data from this input stream. The value byte is
|
||||
// returned as an int in the range 0 to 255. If no byte is available because the
|
||||
// end of the stream has been reached, the value -1 is returned. This method
|
||||
// blocks until input data is available, the end of the stream is detected, or
|
||||
// an exception is thrown. This method simply performs in.read() and returns the
|
||||
// result.
|
||||
int DataInputStream::read() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::read() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
return stream->read();
|
||||
}
|
||||
|
||||
// Reads some number of bytes from the contained input stream and stores them
|
||||
// into the buffer array b. The number of bytes actually read is returned as an
|
||||
// integer. This method blocks until input data is available, end of file is
|
||||
// detected, or an exception is thrown. If b is null, a NullPointerException is
|
||||
// thrown. If the length of b is zero, then no bytes are read and 0 is returned;
|
||||
// otherwise, there is an attempt to read at least one byte. If no byte is
|
||||
// available because the stream is at end of file, the value -1 is returned;
|
||||
// otherwise, at least one byte is read and stored into b.
|
||||
//
|
||||
// The first byte read is stored into element b[0], the next one into b[1], and
|
||||
// so on. The number of bytes read is, at most, equal to the length of b. Let k
|
||||
// be the number of bytes actually read; these bytes will be stored in elements
|
||||
// b[0] through b[k-1], leaving elements b[k] through b[b.length-1] unaffected.
|
||||
//
|
||||
// The read(b) method has the same effect as:
|
||||
//
|
||||
// read(b, 0, b.length)
|
||||
//
|
||||
// Overrides:
|
||||
// read in class FilterInputStream
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 if there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int DataInputStream::read(byteArray b) {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::read(byteArray) called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
// Reads up to len bytes of data from the contained input stream into an array
|
||||
// of bytes. An attempt is made to read as many as len bytes, but a smaller
|
||||
// number may be read, possibly zero. The number of bytes actually read is
|
||||
// returned as an integer. This method blocks until input data is available, end
|
||||
// of file is detected, or an exception is thrown.
|
||||
//
|
||||
// If len is zero, then no bytes are read and 0 is returned; otherwise, there is
|
||||
// an attempt to read at least one byte. If no byte is available because the
|
||||
// stream is at end of file, the value -1 is returned; otherwise, at least one
|
||||
// byte is read and stored into b.
|
||||
//
|
||||
// The first byte read is stored into element b[off], the next one into
|
||||
// b[off+1], and so on. The number of bytes read is, at most, equal to len. Let
|
||||
// k be the number of bytes actually read; these bytes will be stored in
|
||||
// elements b[off] through b[off+k-1], leaving elements b[off+k] through
|
||||
// b[off+len-1] unaffected.
|
||||
//
|
||||
// In every case, elements b[0] through b[off] and elements b[off+len] through
|
||||
// b[b.length-1] are unaffected.
|
||||
//
|
||||
// Overrides:
|
||||
// read in class FilterInputStream
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// off - the start offset in the destination array b
|
||||
// len - the maximum number of bytes read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 if there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int DataInputStream::read(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::read(byteArray,offset,length) called but "
|
||||
"underlying stream is nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
return stream->read(b, offset, length);
|
||||
}
|
||||
|
||||
// Closes this input stream and releases any system resources associated with
|
||||
// the stream. This method simply performs in.close()
|
||||
void DataInputStream::close() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::close() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->close();
|
||||
}
|
||||
|
||||
// Reads one input byte and returns true if that byte is nonzero, false if that
|
||||
// byte is zero. This method is suitable for reading the byte written by the
|
||||
// writeBoolean method of interface DataOutput. Returns: the bool value read.
|
||||
bool DataInputStream::readBoolean() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readBoolean() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return false;
|
||||
}
|
||||
return stream->read() != 0;
|
||||
}
|
||||
|
||||
// Reads and returns one input byte. The byte is treated as a signed value in
|
||||
// the range -128 through 127, inclusive. This method is suitable for reading
|
||||
// the byte written by the writeByte method of interface DataOutput. Returns:
|
||||
// the 8-bit value read.
|
||||
uint8_t DataInputStream::readByte() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readByte() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
return (uint8_t)stream->read();
|
||||
}
|
||||
|
||||
unsigned char DataInputStream::readUnsignedByte() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readUnsignedByte() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
return (unsigned char)stream->read();
|
||||
}
|
||||
|
||||
// Reads two input bytes and returns a char value. Let a be the first byte read
|
||||
// and b be the second byte. The value returned is: (char)((a << 8) | (b &
|
||||
// 0xff))
|
||||
//
|
||||
// This method is suitable for reading bytes written by the writeChar method of
|
||||
// interface DataOutput. Returns: the char value read.
|
||||
wchar_t DataInputStream::readChar() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readChar() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
return (wchar_t)((a << 8) | (b & 0xff));
|
||||
}
|
||||
|
||||
// Reads some bytes from an input stream and stores them into the buffer array
|
||||
// b. The number of bytes read is equal to the length of b. This method blocks
|
||||
// until one of the following conditions occurs:
|
||||
//
|
||||
// b.length bytes of input data are available, in which case a normal return is
|
||||
// made. End of file is detected, in which case an EOFException is thrown. An
|
||||
// I/O error occurs, in which case an IOException other than EOFException is
|
||||
// thrown. If b is null, a NullPointerException is thrown. If b.length is zero,
|
||||
// then no bytes are read. Otherwise, the first byte read is stored into element
|
||||
// b[0], the next one into b[1], and so on. If an exception is thrown from this
|
||||
// method, then it may be that some but not all bytes of b have been updated
|
||||
// with data from the input stream.
|
||||
//
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
bool DataInputStream::readFully(byteArray b) {
|
||||
// TODO 4J Stu - I am not entirely sure if this matches the implementation
|
||||
// of the Java library
|
||||
// TODO 4J Stu - Need to handle exceptions here is we throw them in other
|
||||
// InputStreams
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readFully(byteArray) but underlying stream is "
|
||||
"nullptr\n");
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i = 0; i < b.length; i++) {
|
||||
int byteRead = stream->read();
|
||||
if (byteRead == -1) {
|
||||
return false;
|
||||
} else {
|
||||
b[i] = static_cast<uint8_t>(byteRead);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataInputStream::readFully(charArray b) {
|
||||
// TODO 4J Stu - I am not entirely sure if this matches the implementation
|
||||
// of the Java library
|
||||
// TODO 4J Stu - Need to handle exceptions here is we throw them in other
|
||||
// InputStreams
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readFully(charArray) but underlying stream is "
|
||||
"nullptr\n");
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i = 0; i < b.length; i++) {
|
||||
int byteRead = stream->read();
|
||||
if (byteRead == -1) {
|
||||
return false;
|
||||
} else {
|
||||
b[i] = byteRead;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads eight input bytes and returns a double value. It does this by first
|
||||
// constructing a long value in exactly the manner of the readlong method, then
|
||||
// converting this long value to a double in exactly the manner of the method
|
||||
// Double.longBitsToDouble. This method is suitable for reading bytes written by
|
||||
// the writeDouble method of interface DataOutput. Returns: the double value
|
||||
// read.
|
||||
double DataInputStream::readDouble() {
|
||||
int64_t bits = readLong();
|
||||
|
||||
return std::bit_cast<double>(bits);
|
||||
}
|
||||
|
||||
// Reads four input bytes and returns a float value. It does this by first
|
||||
// constructing an int value in exactly the manner of the readInt method, then
|
||||
// converting this int value to a float in exactly the manner of the method
|
||||
// Float.intBitsToFloat. This method is suitable for reading bytes written by
|
||||
// the writeFloat method of interface DataOutput. Returns: the float value read.
|
||||
float DataInputStream::readFloat() {
|
||||
int bits = readInt();
|
||||
|
||||
return std::bit_cast<float>(bits);
|
||||
}
|
||||
|
||||
// Reads four input bytes and returns an int value. Let a-d be the first through
|
||||
// fourth bytes read. The value returned is:
|
||||
//
|
||||
// (((a & 0xff) << 24) | ((b & 0xff) << 16) |
|
||||
// ((c & 0xff) << 8) | (d & 0xff))
|
||||
//
|
||||
// This method is suitable for reading bytes written by the writeInt method of
|
||||
// interface DataOutput. Returns: the int value read.
|
||||
int DataInputStream::readInt() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readInt() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
int c = stream->read();
|
||||
int d = stream->read();
|
||||
int bits = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) |
|
||||
(d & 0xff));
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Reads eight input bytes and returns a long value. Let a-h be the first
|
||||
// through eighth bytes read. The value returned is:
|
||||
//
|
||||
// (((long)(a & 0xff) << 56) |
|
||||
// ((long)(b & 0xff) << 48) |
|
||||
// ((long)(c & 0xff) << 40) |
|
||||
// ((long)(d & 0xff) << 32) |
|
||||
// ((long)(e & 0xff) << 24) |
|
||||
// ((long)(f & 0xff) << 16) |
|
||||
// ((long)(g & 0xff) << 8) |
|
||||
// ((long)(h & 0xff)))
|
||||
//
|
||||
// This method is suitable for reading bytes written by the writeLong method of
|
||||
// interface DataOutput.
|
||||
//
|
||||
// Returns:
|
||||
// the long value read.
|
||||
int64_t DataInputStream::readLong() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readLong() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int64_t a = stream->read();
|
||||
int64_t b = stream->read();
|
||||
int64_t c = stream->read();
|
||||
int64_t d = stream->read();
|
||||
int64_t e = stream->read();
|
||||
int64_t f = stream->read();
|
||||
int64_t g = stream->read();
|
||||
int64_t h = stream->read();
|
||||
|
||||
int64_t bits =
|
||||
(((a & 0xff) << 56) | ((b & 0xff) << 48) | ((c & 0xff) << 40) |
|
||||
((d & 0xff) << 32) | ((e & 0xff) << 24) | ((f & 0xff) << 16) |
|
||||
((g & 0xff) << 8) | ((h & 0xff)));
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Reads two input bytes and returns a short value. Let a be the first byte read
|
||||
// and b be the second byte. The value returned is: (short)((a << 8) | (b &
|
||||
// 0xff))
|
||||
//
|
||||
// This method is suitable for reading the bytes written by the writeShort
|
||||
// method of interface DataOutput. Returns: the 16-bit value read.
|
||||
short DataInputStream::readShort() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readShort() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
return (short)((a << 8) | (b & 0xff));
|
||||
}
|
||||
|
||||
unsigned short DataInputStream::readUnsignedShort() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readUnsignedShort() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
return static_cast<unsigned short>(((a & 0xff) << 8) | (b & 0xff));
|
||||
}
|
||||
|
||||
// Reads in a string that has been encoded using a modified UTF-8 format. The
|
||||
// general contract of readUTF is that it reads a representation of a Unicode
|
||||
// character string encoded in modified UTF-8 format; this string of characters
|
||||
// is then returned as a String. First, two bytes are read and used to construct
|
||||
// an unsigned 16-bit integer in exactly the manner of the readUnsignedShort
|
||||
// method . This integer value is called the UTF length and specifies the number
|
||||
// of additional bytes to be read. These bytes are then converted to characters
|
||||
// by considering them in groups. The length of each group is computed from the
|
||||
// value of the first byte of the group. The byte following a group, if any, is
|
||||
// the first byte of the next group.
|
||||
//
|
||||
// If the first byte of a group matches the bit pattern 0xxxxxxx (where x means
|
||||
// "may be 0 or 1"), then the group consists of just that byte. The byte is
|
||||
// zero-extended to form a character.
|
||||
//
|
||||
// If the first byte of a group matches the bit pattern 110xxxxx, then the group
|
||||
// consists of that byte a and a second byte b. If there is no byte b (because
|
||||
// byte a was the last of the bytes to be read), or if byte b does not match the
|
||||
// bit pattern 10xxxxxx, then a UTFDataFormatException is thrown. Otherwise, the
|
||||
// group is converted to the character:
|
||||
//
|
||||
//(char)(((a& 0x1F) << 6) | (b & 0x3F))
|
||||
//
|
||||
// If the first byte of a group matches the bit pattern 1110xxxx, then the group
|
||||
// consists of that byte a and two more bytes b and c. If there is no byte c
|
||||
// (because byte a was one of the last two of the bytes to be read), or either
|
||||
// byte b or byte c does not match the bit pattern 10xxxxxx, then a
|
||||
// UTFDataFormatException is thrown. Otherwise, the group is converted to the
|
||||
// character:
|
||||
//
|
||||
// (char)(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F))
|
||||
//
|
||||
// If the first byte of a group matches the pattern 1111xxxx or the pattern
|
||||
// 10xxxxxx, then a UTFDataFormatException is thrown. If end of file is
|
||||
// encountered at any time during this entire process, then an EOFException is
|
||||
// thrown.
|
||||
//
|
||||
// After every group has been converted to a character by this process, the
|
||||
// characters are gathered, in the same order in which their corresponding
|
||||
// groups were read from the input stream, to form a String, which is returned.
|
||||
//
|
||||
// The writeUTF method of interface DataOutput may be used to write data that is
|
||||
// suitable for reading by this method.
|
||||
//
|
||||
// Returns:
|
||||
// a Unicode string.
|
||||
std::wstring DataInputStream::readUTF() {
|
||||
std::wstring outputString;
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readUTF() but underlying stream is nullptr\n");
|
||||
return outputString;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
unsigned short UTFLength = (unsigned short)(((a & 0xff) << 8) | (b & 0xff));
|
||||
|
||||
//// 4J Stu - I decided while writing DataOutputStream that we didn't need
|
||||
/// to bother using the UTF8 format / used in the java libs, and just write
|
||||
/// in/out as wchar_t all the time
|
||||
|
||||
/*for( unsigned short i = 0; i < UTFLength; i++)
|
||||
{
|
||||
wchar_t theChar = readChar();
|
||||
outputString.push_back(theChar);
|
||||
}*/
|
||||
|
||||
unsigned short currentByteIndex = 0;
|
||||
while (currentByteIndex < UTFLength) {
|
||||
int firstByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
if (firstByte == -1)
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
|
||||
// Masking patterns:
|
||||
// 10000000 = 0x80 // Match only highest bit
|
||||
// 11000000 = 0xC0 // Match only highest two bits
|
||||
// 11100000 = 0xE0 // Match only highest three bits
|
||||
// 11110000 = 0xF0 // Match only highest four bits
|
||||
|
||||
// Matching patterns:
|
||||
// 10xxxxxx = 0x80 // ERROR, or second/third byte
|
||||
// 1111xxxx = 0xF0 //ERROR
|
||||
// 0xxxxxxx = 0x00 // One byte UTF
|
||||
// 110xxxxx = 0xC0 // Two byte UTF
|
||||
// 1110xxxx = 0xE0 // Three byte UTF
|
||||
if (((firstByte & 0xC0) == 0x80) || ((firstByte & 0xF0) == 0xF0)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
} else if ((firstByte & 0x80) == 0x00) {
|
||||
// One byte UTF
|
||||
wchar_t readChar = (wchar_t)firstByte;
|
||||
outputString.push_back(readChar);
|
||||
continue;
|
||||
} else if ((firstByte & 0xE0) == 0xC0) {
|
||||
// Two byte UTF
|
||||
|
||||
// No more bytes to read
|
||||
if (!(currentByteIndex < UTFLength)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
int secondByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
}
|
||||
// Incorrect second byte pattern
|
||||
else if ((secondByte & 0xC0) != 0x80) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
wchar_t readChar =
|
||||
(wchar_t)(((firstByte & 0x1F) << 6) | (secondByte & 0x3F));
|
||||
outputString.push_back(readChar);
|
||||
continue;
|
||||
} else if ((firstByte & 0xF0) == 0xE0) {
|
||||
// Three byte UTF
|
||||
|
||||
// No more bytes to read
|
||||
if (!(currentByteIndex < UTFLength)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
int secondByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
}
|
||||
|
||||
// No more bytes to read
|
||||
if (!(currentByteIndex < UTFLength)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
int thirdByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
// No third byte
|
||||
if (thirdByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
}
|
||||
// Incorrect second or third byte pattern
|
||||
else if (((secondByte & 0xC0) != 0x80) ||
|
||||
((thirdByte & 0xC0) != 0x80)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
wchar_t readChar =
|
||||
(wchar_t)(((firstByte & 0x0F) << 12) |
|
||||
((secondByte & 0x3F) << 6) | (thirdByte & 0x3F));
|
||||
outputString.push_back(readChar);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return outputString;
|
||||
}
|
||||
|
||||
int DataInputStream::readUTFChar() {
|
||||
int returnValue = -1;
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataInputStream::readUTFChar() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return returnValue;
|
||||
}
|
||||
int firstByte = stream->read();
|
||||
|
||||
if (firstByte == -1)
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
|
||||
// Masking patterns:
|
||||
// 10000000 = 0x80 // Match only highest bit
|
||||
// 11000000 = 0xC0 // Match only highest two bits
|
||||
// 11100000 = 0xE0 // Match only highest three bits
|
||||
// 11110000 = 0xF0 // Match only highest four bits
|
||||
|
||||
// Matching patterns:
|
||||
// 10xxxxxx = 0x80 // ERROR, or second/third byte
|
||||
// 1111xxxx = 0xF0 //ERROR
|
||||
// 0xxxxxxx = 0x00 // One byte UTF
|
||||
// 110xxxxx = 0xC0 // Two byte UTF
|
||||
// 1110xxxx = 0xE0 // Three byte UTF
|
||||
if (((firstByte & 0xC0) == 0x80) || ((firstByte & 0xF0) == 0xF0)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
return returnValue;
|
||||
} else if ((firstByte & 0x80) == 0x00) {
|
||||
// One byte UTF
|
||||
returnValue = firstByte;
|
||||
} else if ((firstByte & 0xE0) == 0xC0) {
|
||||
// Two byte UTF
|
||||
int secondByte = stream->read();
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
}
|
||||
// Incorrect second byte pattern
|
||||
else if ((secondByte & 0xC0) != 0x80) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
returnValue = ((firstByte & 0x1F) << 6) | (secondByte & 0x3F);
|
||||
} else if ((firstByte & 0xF0) == 0xE0) {
|
||||
// Three byte UTF
|
||||
|
||||
int secondByte = stream->read();
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
int thirdByte = stream->read();
|
||||
|
||||
// No third byte
|
||||
if (thirdByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
}
|
||||
// Incorrect second or third byte pattern
|
||||
else if (((secondByte & 0xC0) != 0x80) ||
|
||||
((thirdByte & 0xC0) != 0x80)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
returnValue = (((firstByte & 0x0F) << 12) | ((secondByte & 0x3F) << 6) |
|
||||
(thirdByte & 0x3F));
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
unsigned long long DataInputStream::readPlayerUID() {
|
||||
unsigned long long returnValue;
|
||||
returnValue = readLong();
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void DataInputStream::deleteChildStream() { delete stream; }
|
||||
|
||||
// Skips n bytes of input from this input stream. Fewer bytes might be skipped
|
||||
// if the end of the input stream is reached. The actual number k of bytes to be
|
||||
// skipped is equal to the smaller of n and count-pos. The value k is added into
|
||||
// pos and k is returned. Overrides: skip in class InputStream Parameters: n -
|
||||
// the number of bytes to be skipped. Returns: the actual number of bytes
|
||||
// skipped.
|
||||
int64_t DataInputStream::skip(int64_t n) { return stream->skip(n); }
|
||||
|
||||
int DataInputStream::skipBytes(int n) { return skip(n); }
|
||||
258
minecraft/java/src/InputOutputStream/DataOutputStream.cpp
Normal file
258
minecraft/java/src/InputOutputStream/DataOutputStream.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
|
||||
#include "InputOutputStream/DataOutputStream.h"
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
// Creates a new data output stream to write data to the specified underlying
|
||||
// output stream. The counter written is set to zero. Parameters: out - the
|
||||
// underlying output stream, to be saved for later use.
|
||||
DataOutputStream::DataOutputStream(OutputStream* out)
|
||||
: stream(out), written(0) {}
|
||||
|
||||
// 4J Stu - We cannot always delete the stream when we are destroyed, but we
|
||||
// want to clear it up as there are occasions when we don't have a handle to the
|
||||
// child stream elsewhere and want to delete it
|
||||
void DataOutputStream::deleteChildStream() { delete stream; }
|
||||
|
||||
// Writes the specified byte (the low eight bits of the argument b) to the
|
||||
// underlying output stream. If no exception is thrown, the counter written is
|
||||
// incremented by 1. Implements the write method of OutputStream. Parameters: b
|
||||
// - the byte to be written.
|
||||
void DataOutputStream::write(unsigned int b) {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataOutputStream::write(unsigned int) called but underlying "
|
||||
"stream is nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->write(b);
|
||||
// TODO 4J Stu - Exception handling?
|
||||
written++;
|
||||
}
|
||||
|
||||
void DataOutputStream::flush() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataOutputStream::flush() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->flush();
|
||||
}
|
||||
|
||||
// Writes b.length bytes from the specified byte array to this output stream.
|
||||
// The general contract for write(b) is that it should have exactly the same
|
||||
// effect as the call write(b, 0, b.length). Parameters: b - the data.
|
||||
void DataOutputStream::write(byteArray b) { write(b, 0, b.length); }
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to the
|
||||
// underlying output stream. If no exception is thrown, the counter written is
|
||||
// incremented by len. Parameters: b - the data. off - the start offset in the
|
||||
// data. len - the number of bytes to write.
|
||||
void DataOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataOutputStream::write(byteArray,...) called but underlying "
|
||||
"stream is nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->write(b, offset, length);
|
||||
// TODO 4J Stu - Some form of error checking?
|
||||
written += length;
|
||||
}
|
||||
|
||||
// Closes this output stream and releases any system resources associated with
|
||||
// the stream. The close method of FilterOutputStream calls its flush method,
|
||||
// and then calls the close method of its underlying output stream.
|
||||
void DataOutputStream::close() {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataOutputStream::close() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->close();
|
||||
}
|
||||
|
||||
// Writes out a byte to the underlying output stream as a 1-byte value. If no
|
||||
// exception is thrown, the counter written is incremented by 1. Parameters: v -
|
||||
// a byte value to be written.
|
||||
void DataOutputStream::writeByte(uint8_t a) {
|
||||
stream->write(static_cast<unsigned int>(a));
|
||||
}
|
||||
|
||||
// Converts the double argument to a long using the doubleToLongBits method in
|
||||
// class Double, and then writes that long value to the underlying output stream
|
||||
// as an 8-byte quantity, high byte first. If no exception is thrown, the
|
||||
// counter written is incremented by 8. Parameters: v - a double value to be
|
||||
// written.
|
||||
void DataOutputStream::writeDouble(double a) {
|
||||
int64_t bits = std::bit_cast<int64_t>(a);
|
||||
|
||||
writeLong(bits);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 8;
|
||||
}
|
||||
|
||||
// Converts the float argument to an int using the floatToIntBits method in
|
||||
// class Float, and then writes that int value to the underlying output stream
|
||||
// as a 4-byte quantity, high byte first. If no exception is thrown, the counter
|
||||
// written is incremented by 4. Parameters: v - a float value to be written.
|
||||
void DataOutputStream::writeFloat(float a) {
|
||||
int bits = std::bit_cast<int>(a);
|
||||
|
||||
writeInt(bits);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 4;
|
||||
}
|
||||
|
||||
// Writes an int to the underlying output stream as four bytes, high byte first.
|
||||
// If no exception is thrown, the counter written is incremented by 4.
|
||||
// Parameters:
|
||||
// v - an int to be written.
|
||||
void DataOutputStream::writeInt(int a) {
|
||||
stream->write((a >> 24) & 0xff);
|
||||
stream->write((a >> 16) & 0xff);
|
||||
stream->write((a >> 8) & 0xff);
|
||||
stream->write(a & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 4;
|
||||
}
|
||||
|
||||
// Writes a long to the underlying output stream as eight bytes, high byte
|
||||
// first. In no exception is thrown, the counter written is incremented by 8.
|
||||
// Parameters:
|
||||
// v - a long to be written.
|
||||
void DataOutputStream::writeLong(int64_t a) {
|
||||
stream->write((a >> 56) & 0xff);
|
||||
stream->write((a >> 48) & 0xff);
|
||||
stream->write((a >> 40) & 0xff);
|
||||
stream->write((a >> 32) & 0xff);
|
||||
stream->write((a >> 24) & 0xff);
|
||||
stream->write((a >> 16) & 0xff);
|
||||
stream->write((a >> 8) & 0xff);
|
||||
stream->write(a & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 4;
|
||||
}
|
||||
|
||||
// Writes a short to the underlying output stream as two bytes, high byte first.
|
||||
// If no exception is thrown, the counter written is incremented by 2.
|
||||
// Parameters:
|
||||
// v - a short to be written.
|
||||
void DataOutputStream::writeShort(short a) {
|
||||
stream->write((a >> 8) & 0xff);
|
||||
stream->write(a & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 2;
|
||||
}
|
||||
|
||||
void DataOutputStream::writeUnsignedShort(unsigned short a) {
|
||||
if (stream == nullptr) {
|
||||
fprintf(stderr,
|
||||
"DataOutputStream::writeUnsignedShort() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->write(static_cast<unsigned int>((a >> 8) & 0xff));
|
||||
stream->write(static_cast<unsigned int>(a & 0xff));
|
||||
written += 2;
|
||||
}
|
||||
|
||||
// Writes a char to the underlying output stream as a 2-byte value, high byte
|
||||
// first. If no exception is thrown, the counter written is incremented by 2.
|
||||
// Parameters:
|
||||
// v - a char value to be written.
|
||||
void DataOutputStream::writeChar(wchar_t v) {
|
||||
stream->write((v >> 8) & 0xff);
|
||||
stream->write(v & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 2;
|
||||
}
|
||||
|
||||
// Writes a string to the underlying output stream as a sequence of characters.
|
||||
// Each character is written to the data output stream as if by the writeChar
|
||||
// method. If no exception is thrown, the counter written is incremented by
|
||||
// twice the length of s. Parameters: s - a String value to be written.
|
||||
void DataOutputStream::writeChars(const std::wstring& str) {
|
||||
for (unsigned int i = 0; i < str.length(); i++) {
|
||||
writeChar(str.at(i));
|
||||
// TODO 4J Stu - Error handling?
|
||||
}
|
||||
// Incrementing handled by the writeChar function
|
||||
}
|
||||
|
||||
// Writes a bool to the underlying output stream as a 1-byte value.
|
||||
// The value true is written out as the value (uint8_t)1; the value false is
|
||||
// written out as the value (uint8_t)0. If no exception is thrown, the counter
|
||||
// written is incremented by 1. Parameters: v - a bool value to be written.
|
||||
void DataOutputStream::writeBoolean(bool b) {
|
||||
stream->write(b ? 1 : 0);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 1;
|
||||
}
|
||||
|
||||
// Writes a string to the underlying output stream using modified UTF-8 encoding
|
||||
// in a machine-independent manner. First, two bytes are written to the output
|
||||
// stream as if by the writeShort method giving the number of bytes to follow.
|
||||
// This value is the number of bytes actually written out, not the length of the
|
||||
// string. Following the length, each character of the string is output, in
|
||||
// sequence, using the modified UTF-8 encoding for the character. If no
|
||||
// exception is thrown, the counter written is incremented by the total number
|
||||
// of bytes written to the output stream. This will be at least two plus the
|
||||
// length of str, and at most two plus thrice the length of str. Parameters: str
|
||||
// - a string to be written.
|
||||
void DataOutputStream::writeUTF(const std::wstring& str) {
|
||||
int strlen = (int)str.length();
|
||||
int utflen = 0;
|
||||
int c, count = 0;
|
||||
|
||||
/* use charAt instead of copying String to char array */
|
||||
for (int i = 0; i < strlen; i++) {
|
||||
c = str.at(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
utflen++;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// if (utflen > 65535)
|
||||
// throw new UTFDataFormatException(
|
||||
// "encoded string too long: " + utflen + " bytes");
|
||||
|
||||
byteArray bytearr(utflen + 2);
|
||||
|
||||
bytearr[count++] = (uint8_t)((utflen >> 8) & 0xFF);
|
||||
bytearr[count++] = (uint8_t)((utflen >> 0) & 0xFF);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < strlen; i++) {
|
||||
c = str.at(i);
|
||||
if (!((c >= 0x0001) && (c <= 0x007F))) break;
|
||||
bytearr[count++] = (uint8_t)c;
|
||||
}
|
||||
|
||||
for (; i < strlen; i++) {
|
||||
c = str.at(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
bytearr[count++] = (uint8_t)c;
|
||||
|
||||
} else if (c > 0x07FF) {
|
||||
bytearr[count++] = (uint8_t)(0xE0 | ((c >> 12) & 0x0F));
|
||||
bytearr[count++] = (uint8_t)(0x80 | ((c >> 6) & 0x3F));
|
||||
bytearr[count++] = (uint8_t)(0x80 | ((c >> 0) & 0x3F));
|
||||
} else {
|
||||
bytearr[count++] = (uint8_t)(0xC0 | ((c >> 6) & 0x1F));
|
||||
bytearr[count++] = (uint8_t)(0x80 | ((c >> 0) & 0x3F));
|
||||
}
|
||||
}
|
||||
write(bytearr, 0, utflen + 2);
|
||||
delete[] bytearr.data;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
void DataOutputStream::writePlayerUID(unsigned long long player) { writeLong(player); }
|
||||
187
minecraft/java/src/InputOutputStream/FileInputStream.cpp
Normal file
187
minecraft/java/src/InputOutputStream/FileInputStream.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
#include "File.h"
|
||||
#include "InputOutputStream/FileInputStream.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/StringHelpers.h"
|
||||
|
||||
namespace {
|
||||
int64_t FileTell(std::FILE* file) {
|
||||
#if defined(_WIN32)
|
||||
return _ftelli64(file);
|
||||
#else
|
||||
return static_cast<int64_t>(ftello(file));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FileSeek(std::FILE* file, int64_t offset, int origin) {
|
||||
#if defined(_WIN32)
|
||||
return _fseeki64(file, offset, origin) == 0;
|
||||
#else
|
||||
return fseeko(file, static_cast<off_t>(offset), origin) == 0;
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Creates a FileInputStream by opening a connection to an actual file, the file
|
||||
// named by the File object file in the file system. A new FileDescriptor object
|
||||
// is created to represent this file connection. First, if there is a security
|
||||
// manager, its checkRead method is called with the path represented by the file
|
||||
// argument as its argument.
|
||||
//
|
||||
// If the named file does not exist, is a directory rather than a regular file,
|
||||
// or for some other reason cannot be opened for reading then a
|
||||
// FileNotFoundException is thrown.
|
||||
//
|
||||
// Parameters:
|
||||
// file - the file to be opened for reading.
|
||||
// Throws:
|
||||
// FileNotFoundException - if the file does not exist, is a directory rather
|
||||
// than a regular file, or for some other reason cannot be opened for reading.
|
||||
// SecurityException - if a security manager exists and its checkRead method
|
||||
// denies read access to the file.
|
||||
FileInputStream::FileInputStream(const File& file) : m_fileHandle(nullptr) {
|
||||
#if defined(_WIN32)
|
||||
m_fileHandle = _wfopen(file.getPath().c_str(), L"rb");
|
||||
#else
|
||||
const std::string nativePath = wstringtofilename(file.getPath());
|
||||
m_fileHandle = std::fopen(nativePath.c_str(), "rb");
|
||||
#endif
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
FileInputStream::~FileInputStream() {
|
||||
if (m_fileHandle != nullptr) {
|
||||
std::fclose(m_fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Reads a byte of data from this input stream. This method blocks if no input
|
||||
// is yet available. Returns: the next byte of data, or -1 if the end of the
|
||||
// file is reached.
|
||||
int FileInputStream::read() {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::uint8_t byteRead = static_cast<std::uint8_t>(0);
|
||||
const size_t numberOfBytesRead = std::fread(&byteRead, 1, 1, m_fileHandle);
|
||||
|
||||
if (std::ferror(m_fileHandle) != 0) {
|
||||
assert(0);
|
||||
} else if (numberOfBytesRead == 0) {
|
||||
// File pointer is past the end of the file
|
||||
return -1;
|
||||
}
|
||||
|
||||
return static_cast<int>(byteRead);
|
||||
}
|
||||
|
||||
// Reads up to b.length bytes of data from this input stream into an array of
|
||||
// bytes. This method blocks until some input is available. Parameters: b - the
|
||||
// buffer into which the data is read. Returns: the total number of bytes read
|
||||
// into the buffer, or -1 if there is no more data because the end of the file
|
||||
// has been reached.
|
||||
int FileInputStream::read(byteArray b) {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesRead =
|
||||
std::fread(b.data, 1, b.length, m_fileHandle);
|
||||
|
||||
if (std::ferror(m_fileHandle) != 0) {
|
||||
assert(0);
|
||||
} else if (numberOfBytesRead == 0) {
|
||||
// File pointer is past the end of the file
|
||||
return -1;
|
||||
}
|
||||
|
||||
return numberOfBytesRead;
|
||||
}
|
||||
|
||||
// Reads up to len bytes of data from this input stream into an array of bytes.
|
||||
// If len is not zero, the method blocks until some input is available;
|
||||
// otherwise, no bytes are read and 0 is returned. Parameters: b - the buffer
|
||||
// into which the data is read. off - the start offset in the destination array
|
||||
// b len - the maximum number of bytes read. Returns: the total number of bytes
|
||||
// read into the buffer, or -1 if there is no more data because the end of the
|
||||
// file has been reached.
|
||||
int FileInputStream::read(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
// 4J Stu - We don't want to read any more than the array buffer can hold
|
||||
assert(length <= (b.length - offset));
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesRead =
|
||||
std::fread(&b[offset], 1, length, m_fileHandle);
|
||||
|
||||
if (std::ferror(m_fileHandle) != 0) {
|
||||
assert(0);
|
||||
} else if (numberOfBytesRead == 0) {
|
||||
// File pointer is past the end of the file
|
||||
return -1;
|
||||
}
|
||||
|
||||
return numberOfBytesRead;
|
||||
}
|
||||
|
||||
// Closes this file input stream and releases any system resources associated
|
||||
// with the stream. If this stream has an associated channel then the channel is
|
||||
// closed as well.
|
||||
void FileInputStream::close() {
|
||||
if (m_fileHandle == nullptr) {
|
||||
// printf("\n\nFileInputStream::close - TRYING TO CLOSE AN INVALID FILE
|
||||
// void*\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int result = std::fclose(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
}
|
||||
|
||||
// Stop the dtor from trying to close it again
|
||||
m_fileHandle = nullptr;
|
||||
}
|
||||
|
||||
// Skips n bytes of input from this input stream. Fewer bytes might be skipped
|
||||
// if the end of the input stream is reached. The actual number k of bytes to be
|
||||
// skipped is equal to the smaller of n and count-pos. The value k is added into
|
||||
// pos and k is returned. Overrides: skip in class InputStream Parameters: n -
|
||||
// the number of bytes to be skipped. Returns: the actual number of bytes
|
||||
// skipped.
|
||||
int64_t FileInputStream::skip(int64_t n) {
|
||||
if (m_fileHandle == nullptr || n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64_t start = FileTell(m_fileHandle);
|
||||
if (start < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FileSeek(m_fileHandle, 0, SEEK_END)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64_t end = FileTell(m_fileHandle);
|
||||
if (end < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64_t offset = std::min(n, std::max<int64_t>(0, end - start));
|
||||
const int64_t target = start + offset;
|
||||
if (!FileSeek(m_fileHandle, target, SEEK_SET)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
124
minecraft/java/src/InputOutputStream/FileOutputStream.cpp
Normal file
124
minecraft/java/src/InputOutputStream/FileOutputStream.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "File.h"
|
||||
#include "InputOutputStream/FileOutputStream.h"
|
||||
|
||||
#include "../../../Minecraft.World/ConsoleHelpers/ArrayWithLength.h" // 4jcraft TODO
|
||||
|
||||
// Creates a file output stream to write to the file represented by the
|
||||
// specified File object. A new FileDescriptor object is created to represent
|
||||
// this file connection. First, if there is a security manager, its checkWrite
|
||||
// method is called with the path represented by the file argument as its
|
||||
// argument.
|
||||
//
|
||||
// If the file exists but is a directory rather than a regular file, does not
|
||||
// exist but cannot be created, or cannot be opened for any other reason then a
|
||||
// FileNotFoundException is thrown.
|
||||
//
|
||||
// Parameters:
|
||||
// file - the file to be opened for writing.
|
||||
FileOutputStream::FileOutputStream(const File& file) : m_fileHandle(nullptr) {
|
||||
if (file.exists() && file.isDirectory()) {
|
||||
// TODO 4J Stu - FileNotFoundException
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
m_fileHandle = _wfopen(file.getPath().c_str(), L"wb");
|
||||
#else
|
||||
const std::string nativePath = wstringtofilename(file.getPath());
|
||||
m_fileHandle = std::fopen(nativePath.c_str(), "wb");
|
||||
#endif
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
// TODO 4J Stu - Any form of error/exception handling
|
||||
perror("FileOutputStream::FileOutputStream");
|
||||
}
|
||||
}
|
||||
|
||||
FileOutputStream::~FileOutputStream() {
|
||||
if (m_fileHandle != nullptr) {
|
||||
std::fclose(m_fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Writes the specified byte to this file output stream. Implements the write
|
||||
// method of OutputStream. Parameters: b - the byte to be written.
|
||||
void FileOutputStream::write(unsigned int b) {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::uint8_t value = (std::uint8_t)b;
|
||||
const size_t numberOfBytesWritten = std::fwrite(&value, 1, 1, m_fileHandle);
|
||||
const int result = std::ferror(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
} else if (numberOfBytesWritten == 0) {
|
||||
// File pointer is past the end of the file
|
||||
}
|
||||
}
|
||||
|
||||
// Writes b.length bytes from the specified byte array to this file output
|
||||
// stream. Parameters: b - the data.
|
||||
void FileOutputStream::write(byteArray b) {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesWritten =
|
||||
std::fwrite(b.data, 1, b.length, m_fileHandle);
|
||||
const int result = std::ferror(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
} else if (numberOfBytesWritten == 0 || numberOfBytesWritten != b.length) {
|
||||
// File pointer is past the end of the file
|
||||
}
|
||||
}
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to this
|
||||
// file output stream. Parameters: b - the data. off - the start offset in the
|
||||
// data. len - the number of bytes to write.
|
||||
void FileOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
// 4J Stu - We don't want to write any more than the array buffer holds
|
||||
assert(length <= (b.length - offset));
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesWritten =
|
||||
std::fwrite(&b[offset], 1, length, m_fileHandle);
|
||||
const int result = std::ferror(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
} else if (numberOfBytesWritten == 0 || numberOfBytesWritten != length) {
|
||||
// File pointer is past the end of the file
|
||||
}
|
||||
}
|
||||
//
|
||||
// Closes this file output stream and releases any system resources associated
|
||||
// with this stream. This file output stream may no longer be used for writing
|
||||
// bytes. If this stream has an associated channel then the channel is closed as
|
||||
// well.
|
||||
void FileOutputStream::close() {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int result = std::fclose(m_fileHandle);
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
}
|
||||
|
||||
// Stop the dtor from trying to close it again
|
||||
m_fileHandle = nullptr;
|
||||
}
|
||||
|
||||
void FileOutputStream::flush() {
|
||||
if (m_fileHandle != nullptr) {
|
||||
std::fflush(m_fileHandle);
|
||||
}
|
||||
}
|
||||
8
minecraft/java/src/InputOutputStream/InputStream.cpp
Normal file
8
minecraft/java/src/InputOutputStream/InputStream.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "File.h"
|
||||
#include "InputOutputStream/InputOutputStream.h"
|
||||
#include "InputOutputStream/InputStream.h"
|
||||
|
||||
InputStream* InputStream::getResourceAsStream(const std::wstring& fileName) {
|
||||
File file(fileName);
|
||||
return file.exists() ? new FileInputStream(file) : nullptr;
|
||||
}
|
||||
46
minecraft/java/src/InputOutputStream/InputStreamReader.cpp
Normal file
46
minecraft/java/src/InputOutputStream/InputStreamReader.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
#include "InputOutputStream/InputStream.h"
|
||||
#include "InputOutputStream/DataInputStream.h"
|
||||
#include "InputOutputStream/InputStreamReader.h"
|
||||
|
||||
// Creates an InputStreamReader that uses the default charset.
|
||||
// Parameters:
|
||||
// in - An InputStream
|
||||
InputStreamReader::InputStreamReader(InputStream* in)
|
||||
: stream(new DataInputStream(in)) {}
|
||||
|
||||
// Closes the stream and releases any system resources associated with it.
|
||||
// Once the stream has been closed, further read(), ready(), mark(), reset(), or
|
||||
// skip() invocations will throw an IOException. Closing a previously closed
|
||||
// stream has no effect.
|
||||
void InputStreamReader::close() { stream->close(); }
|
||||
|
||||
// Reads a single character.
|
||||
// Returns:
|
||||
// The character read, or -1 if the end of the stream has been reached
|
||||
int InputStreamReader::read() { return stream->readUTFChar(); }
|
||||
|
||||
// Reads characters into a portion of an array.
|
||||
// Parameters:
|
||||
// cbuf - Destination buffer
|
||||
// offset - Offset at which to start storing characters
|
||||
// length - Maximum number of characters to read
|
||||
// Returns:
|
||||
// The number of characters read, or -1 if the end of the stream has been
|
||||
// reached
|
||||
int InputStreamReader::read(wchar_t cbuf[], unsigned int offset,
|
||||
unsigned int length) {
|
||||
unsigned int charsRead = 0;
|
||||
for (unsigned int i = offset; i < offset + length; i++) {
|
||||
wchar_t value = (wchar_t)stream->readUTFChar();
|
||||
if (value != -1) {
|
||||
cbuf[i] = value;
|
||||
charsRead++;
|
||||
}
|
||||
// TODO 4J Stu - The read might throw an exception? In which case we
|
||||
// should return -1
|
||||
else
|
||||
break;
|
||||
}
|
||||
return charsRead;
|
||||
}
|
||||
108
minecraft/java/src/IntBuffer.cpp
Normal file
108
minecraft/java/src/IntBuffer.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
#include "IntBuffer.h"
|
||||
|
||||
// Allocates a new int buffer.
|
||||
// The new buffer's position will be zero, its limit will be its capacity, and
|
||||
// its mark will be undefined. It will have a backing array, and its array
|
||||
// offset will be zero.
|
||||
//
|
||||
// Parameters:
|
||||
// capacity - The new buffer's capacity, in ints
|
||||
IntBuffer::IntBuffer(unsigned int capacity) : Buffer(capacity) {
|
||||
buffer = new int[capacity];
|
||||
memset(buffer, 0, sizeof(int) * capacity);
|
||||
}
|
||||
|
||||
IntBuffer::IntBuffer(unsigned int capacity, int* backingArray)
|
||||
: Buffer(capacity) {
|
||||
hasBackingArray = true;
|
||||
buffer = backingArray;
|
||||
}
|
||||
|
||||
IntBuffer::~IntBuffer() {
|
||||
if (!hasBackingArray) delete[] buffer;
|
||||
}
|
||||
|
||||
int* IntBuffer::getBuffer() { return buffer; }
|
||||
|
||||
// Flips this buffer. The limit is set to the current position and then the
|
||||
// position is set to zero. If the mark is defined then it is discarded.
|
||||
//
|
||||
// Returns:
|
||||
// This buffer
|
||||
IntBuffer* IntBuffer::flip() {
|
||||
m_limit = m_position;
|
||||
m_position = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Absolute get method. Reads the int at the given index.
|
||||
// Parameters:
|
||||
// index - The index from which the int will be read
|
||||
// Returns:
|
||||
// The int at the given index
|
||||
int IntBuffer::get(unsigned int index) {
|
||||
assert(index < m_limit);
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
// Relative bulk put method (optional operation).
|
||||
// This method transfers ints into this buffer from the given source array.
|
||||
// If there are more ints to be copied from the array than remain in this
|
||||
// buffer, that is, if length > remaining(), then no ints are transferred and a
|
||||
// BufferOverflowException is thrown.
|
||||
//
|
||||
// Otherwise, this method copies length ints from the given array into this
|
||||
// buffer, starting at the given offset in the array and at the current position
|
||||
// of this buffer. The position of this buffer is then incremented by length.
|
||||
//
|
||||
// In other words, an invocation of this method of the form dst.put(src, off,
|
||||
// len) has exactly the same effect as the loop
|
||||
//
|
||||
// for (int i = off; i < off + len; i++)
|
||||
// dst.put(a[i]);
|
||||
// except that it first checks that there is sufficient space in this buffer and
|
||||
// it is potentially much more efficient. Parameters: src - The array from which
|
||||
// ints are to be read offset - The offset within the array of the first int to
|
||||
// be read; must be non-negative and no larger than array.length length - The
|
||||
// number of ints to be read from the given array; must be non-negative and no
|
||||
// larger than array.length - offset Returns: This buffer
|
||||
IntBuffer* IntBuffer::put(intArray* inputArray, unsigned int offset,
|
||||
unsigned int length) {
|
||||
assert(offset + length < inputArray->length);
|
||||
|
||||
std::copy(inputArray->data + offset, inputArray->data + offset + length,
|
||||
buffer + m_position);
|
||||
|
||||
m_position += length;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
IntBuffer* IntBuffer::put(intArray inputArray) {
|
||||
if (inputArray.length > remaining())
|
||||
assert(false); // TODO 4J Stu - Some kind of exception?
|
||||
|
||||
std::copy(inputArray.data, inputArray.data + inputArray.length,
|
||||
buffer + m_position);
|
||||
|
||||
m_position += inputArray.length;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Writes the given int into this buffer at the current position, and then
|
||||
// increments the position.
|
||||
//
|
||||
// Parameters:
|
||||
// i - The int to be written
|
||||
// Returns:
|
||||
// This buffer
|
||||
IntBuffer* IntBuffer::put(int i) {
|
||||
assert(m_position < m_limit);
|
||||
|
||||
buffer[m_position++] = i;
|
||||
|
||||
return this;
|
||||
}
|
||||
74
minecraft/java/src/JavaMath.cpp
Normal file
74
minecraft/java/src/JavaMath.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "JavaMath.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
Random Math::rand = Random();
|
||||
|
||||
// Returns a double value with a positive sign, greater than or equal to 0.0 and
|
||||
// less than 1.0. Returned values are chosen pseudorandomly with (approximately)
|
||||
// uniform distribution from that range. When this method is first called, it
|
||||
// creates a single new pseudorandom-number generator, exactly as if by the
|
||||
// expression
|
||||
//
|
||||
// new java.util.Random
|
||||
// This new pseudorandom-number generator is used thereafter for all calls to
|
||||
// this method and is used nowhere else. This method is properly synchronized to
|
||||
// allow correct use by more than one thread. However, if many threads need to
|
||||
// generate pseudorandom numbers at a great rate, it may reduce contention for
|
||||
// each thread to have its own pseudorandom-number generator.
|
||||
//
|
||||
// Returns:
|
||||
// a pseudorandom double greater than or equal to 0.0 and less than 1.0.
|
||||
double Math::random() { return Math::rand.nextDouble(); }
|
||||
|
||||
// Returns the closest long to the argument. The result is rounded to an integer
|
||||
// by adding 1/2, taking the floor of the result, and casting the result to type
|
||||
// long. In other words, the result is equal to the value of the expression:
|
||||
//(long)Math.floor(a + 0.5d)
|
||||
// Special cases:
|
||||
//
|
||||
// If the argument is NaN, the result is 0.
|
||||
// If the argument is negative infinity or any value less than or equal to the
|
||||
// value of Long.MIN_VALUE, the result is equal to the value of Long.MIN_VALUE.
|
||||
// If the argument is positive infinity or any value greater than or equal to
|
||||
// the value of Long.MAX_VALUE, the result is equal to the value of
|
||||
// Long.MAX_VALUE. Parameters: a - a floating-point value to be rounded to a
|
||||
// long. Returns: the value of the argument rounded to the nearest long value.
|
||||
int64_t Math::round(double d) {
|
||||
// 4jcraft fixes the fact that if double is a huge
|
||||
// number than the cast of d to int64_t overflows
|
||||
|
||||
d = std::floor(d + 0.5);
|
||||
|
||||
// if smaller or bigger than representable int64 than return the max
|
||||
if (d >= (double)INT64_MAX) {
|
||||
return INT64_MAX;
|
||||
|
||||
} else if (d <= (double)INT64_MIN) {
|
||||
return INT64_MIN;
|
||||
}
|
||||
|
||||
return (int64_t)d;
|
||||
}
|
||||
|
||||
int Math::_max(int a, int b) { return a > b ? a : b; }
|
||||
|
||||
int Math::_min(int a, int b) { return a < b ? a : b; }
|
||||
|
||||
float Math::_max(float a, float b) { return a > b ? a : b; }
|
||||
|
||||
float Math::_min(float a, float b) { return a < b ? a : b; }
|
||||
|
||||
float Math::wrapDegrees(float input) {
|
||||
while (input >= 360.0f) input -= 360.0f;
|
||||
if (input >= 180.0f) input -= 360.0f;
|
||||
if (input < -180.0f) input += 360.0f;
|
||||
return input;
|
||||
}
|
||||
|
||||
double Math::wrapDegrees(double input) {
|
||||
while (input >= 360.0) input -= 360.0;
|
||||
if (input >= 180.0) input -= 360.0;
|
||||
if (input < -180.0) input += 360.0;
|
||||
return input;
|
||||
}
|
||||
90
minecraft/java/src/Random.cpp
Normal file
90
minecraft/java/src/Random.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "Random.h"
|
||||
#include <ctime>
|
||||
#include <cstdint> // for int64_t
|
||||
#include "System.h"
|
||||
|
||||
Random::Random() {
|
||||
// 4J - jave now uses the system nanosecond counter added to a
|
||||
// "seedUniquifier" to get an initial seed. Our nanosecond timer is actually
|
||||
// only millisecond accuate, so use QueryPerformanceCounter here instead
|
||||
int64_t seed;
|
||||
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
||||
seed = ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
||||
|
||||
seed += 8682522807148012LL;
|
||||
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
Random::Random(int64_t seed) { setSeed(seed); }
|
||||
|
||||
void Random::setSeed(int64_t s) {
|
||||
this->seed = (s ^ 0x5DEECE66DLL) & ((1LL << 48) - 1);
|
||||
haveNextNextGaussian = false;
|
||||
}
|
||||
|
||||
int Random::next(int bits) {
|
||||
// 4jcraft, cast to uint64_t for modulo arithmethic
|
||||
// overflow of int undefined, and its guaranteed here.
|
||||
seed = ((uint64_t)seed * 0x5DEECE66DLL + 0xBLL) & ((1LL << 48) - 1);
|
||||
return (int)(seed >> (48 - bits));
|
||||
}
|
||||
|
||||
void Random::nextBytes(uint8_t* bytes, unsigned int count) {
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
bytes[i] = (uint8_t)next(8);
|
||||
}
|
||||
}
|
||||
|
||||
double Random::nextDouble() {
|
||||
return (((int64_t)next(26) << 27) + next(27)) / (double)(1LL << 53);
|
||||
}
|
||||
|
||||
double Random::nextGaussian() {
|
||||
if (haveNextNextGaussian) {
|
||||
haveNextNextGaussian = false;
|
||||
return nextNextGaussian;
|
||||
} else {
|
||||
double v1, v2, s;
|
||||
do {
|
||||
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
|
||||
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
|
||||
s = v1 * v1 + v2 * v2;
|
||||
} while (s >= 1 || s == 0);
|
||||
double multiplier = sqrt(-2 * log(s) / s);
|
||||
nextNextGaussian = v2 * multiplier;
|
||||
haveNextNextGaussian = true;
|
||||
return v1 * multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
int Random::nextInt() { return next(32); }
|
||||
|
||||
int Random::nextInt(int n) {
|
||||
assert(n > 0);
|
||||
|
||||
if ((n & -n) == n) // i.e., n is a power of 2
|
||||
// 4jcraft added casts to unsigned (and uint64_t)
|
||||
return (int)(((uint64_t)next(31) * n) >>
|
||||
31); // 4J Stu - Made int64_t instead of long
|
||||
|
||||
int bits, val;
|
||||
do {
|
||||
bits = next(31);
|
||||
val = bits % n;
|
||||
// 4jcraft added a cast to prevent overflow
|
||||
} while ((int64_t)bits - val + (n - 1) < 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
float Random::nextFloat() { return next(24) / ((float)(1 << 24)); }
|
||||
|
||||
int64_t Random::nextLong() {
|
||||
// 4jcraft added casts to unsigned
|
||||
return (int64_t)((uint64_t)next(32) << 32) + next(32);
|
||||
}
|
||||
|
||||
bool Random::nextBoolean() { return next(1) != 0; }
|
||||
181
minecraft/java/src/system.cpp
Normal file
181
minecraft/java/src/system.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "System.h"
|
||||
#if defined(__linux__)
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void System::arraycopy(arrayWithLength<T> src, unsigned int srcPos,
|
||||
arrayWithLength<T>* dst, unsigned int dstPos,
|
||||
unsigned int length) {
|
||||
assert(srcPos >= 0 && srcPos <= src.length);
|
||||
assert(srcPos + length <= src.length);
|
||||
assert(dstPos + length <= dst->length);
|
||||
|
||||
std::copy(src.data + srcPos, src.data + srcPos + length,
|
||||
dst->data + dstPos);
|
||||
}
|
||||
|
||||
ArrayCopyFunctionDefinition(Node*) ArrayCopyFunctionDefinition(Biome*)
|
||||
|
||||
void System::arraycopy(arrayWithLength<uint8_t> src, unsigned int srcPos,
|
||||
arrayWithLength<uint8_t>* dst, unsigned int dstPos,
|
||||
unsigned int length) {
|
||||
assert(srcPos >= 0 && srcPos <= src.length);
|
||||
assert(srcPos + length <= src.length);
|
||||
assert(dstPos + length <= dst->length);
|
||||
|
||||
memcpy(dst->data + dstPos, src.data + srcPos, length);
|
||||
}
|
||||
|
||||
void System::arraycopy(arrayWithLength<int> src, unsigned int srcPos,
|
||||
arrayWithLength<int>* dst, unsigned int dstPos,
|
||||
unsigned int length) {
|
||||
assert(srcPos >= 0 && srcPos <= src.length);
|
||||
assert(srcPos + length <= src.length);
|
||||
assert(dstPos + length <= dst->length);
|
||||
|
||||
memcpy(dst->data + dstPos, src.data + srcPos, length * sizeof(int));
|
||||
}
|
||||
|
||||
// TODO 4J Stu - These time functions may suffer from accuracy and we might have
|
||||
// to use a high-resolution timer
|
||||
// Returns the current value of the most precise available system timer, in
|
||||
// nanoseconds. This method can only be used to measure elapsed time and is not
|
||||
// related to any other notion of system or wall-clock time. The value returned
|
||||
// represents nanoseconds since some fixed but arbitrary time (perhaps in the
|
||||
// future, so values may be negative). This method provides nanosecond
|
||||
// precision, but not necessarily nanosecond accuracy. No guarantees are made
|
||||
// about how frequently values change. Differences in successive calls that span
|
||||
// greater than approximately 292 years (263 nanoseconds) will not accurately
|
||||
// compute elapsed time due to numerical overflow.
|
||||
//
|
||||
// For example, to measure how long some code takes to execute:
|
||||
//
|
||||
// long startTime = System.nanoTime();
|
||||
// // ... the code being measured ...
|
||||
// long estimatedTime = System.nanoTime() - startTime;
|
||||
//
|
||||
// Returns:
|
||||
// The current value of the system timer, in nanoseconds.
|
||||
int64_t System::nanoTime() {
|
||||
#if !defined(__linux__)
|
||||
return GetTickCount() * 1000000LL;
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return static_cast<int64_t>(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the current time in milliseconds. Note that while the unit of time of
|
||||
// the return value is a millisecond, the granularity of the value depends on
|
||||
// the underlying operating system and may be larger. For example, many
|
||||
// operating systems measure time in units of tens of milliseconds. See the
|
||||
// description of the class Date for a discussion of slight discrepancies that
|
||||
// may arise between "computer time" and coordinated universal time (UTC).
|
||||
//
|
||||
// Returns:
|
||||
// the difference, measured in milliseconds, between the current time and
|
||||
// midnight, January 1, 1970 UTC.
|
||||
int64_t System::currentTimeMillis() {
|
||||
#if defined(__linux__)
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
// Convert to milliseconds since unix epoch instead of windows file time
|
||||
// time is expecting calculation to be between 10-30 ms.
|
||||
return (int64_t)tv.tv_sec * 1000LL + tv.tv_usec / 1000;
|
||||
#else
|
||||
|
||||
SYSTEMTIME UTCSysTime;
|
||||
GetSystemTime(&UTCSysTime);
|
||||
|
||||
// Represents as a 64-bit value the number of 100-nanosecond intervals since
|
||||
// January 1, 1601
|
||||
FILETIME UTCFileTime;
|
||||
SystemTimeToFileTime(&UTCSysTime, &UTCFileTime);
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.HighPart = UTCFileTime.dwHighDateTime;
|
||||
li.LowPart = UTCFileTime.dwLowDateTime;
|
||||
|
||||
return li.QuadPart / 10000;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 4J Stu - Added this so that we can use real-world timestamps in PSVita saves.
|
||||
// Particularly required for the save transfers to be smooth
|
||||
int64_t System::currentRealTimeMillis() { return currentTimeMillis(); }
|
||||
|
||||
void System::ReverseUSHORT(unsigned short* pusVal) {
|
||||
unsigned short usValue = *pusVal;
|
||||
unsigned char* pchVal1 = (unsigned char*)pusVal;
|
||||
unsigned char* pchVal2 = (unsigned char*)&usValue;
|
||||
|
||||
pchVal1[0] = pchVal2[1];
|
||||
pchVal1[1] = pchVal2[0];
|
||||
}
|
||||
|
||||
void System::ReverseSHORT(short* pusVal) {
|
||||
short usValue = *pusVal;
|
||||
unsigned char* pchVal1 = (unsigned char*)pusVal;
|
||||
unsigned char* pchVal2 = (unsigned char*)&usValue;
|
||||
|
||||
pchVal1[0] = pchVal2[1];
|
||||
pchVal1[1] = pchVal2[0];
|
||||
}
|
||||
|
||||
void System::ReverseULONG(unsigned long* pulVal) {
|
||||
unsigned long ulValue = *pulVal;
|
||||
unsigned char* pchVal1 = (unsigned char*)pulVal;
|
||||
unsigned char* pchVal2 = (unsigned char*)&ulValue;
|
||||
|
||||
pchVal1[0] = pchVal2[3];
|
||||
pchVal1[1] = pchVal2[2];
|
||||
pchVal1[2] = pchVal2[1];
|
||||
pchVal1[3] = pchVal2[0];
|
||||
}
|
||||
|
||||
void System::ReverseULONG(unsigned int* pulVal) {
|
||||
unsigned int ulValue = *pulVal;
|
||||
unsigned char* pchVal1 = (unsigned char*)pulVal;
|
||||
unsigned char* pchVal2 = (unsigned char*)&ulValue;
|
||||
|
||||
pchVal1[0] = pchVal2[3];
|
||||
pchVal1[1] = pchVal2[2];
|
||||
pchVal1[2] = pchVal2[1];
|
||||
pchVal1[3] = pchVal2[0];
|
||||
}
|
||||
|
||||
void System::ReverseINT(int* piVal) {
|
||||
int ulValue = *piVal;
|
||||
unsigned char* pchVal1 = (unsigned char*)piVal;
|
||||
unsigned char* pchVal2 = (unsigned char*)&ulValue;
|
||||
|
||||
pchVal1[0] = pchVal2[3];
|
||||
pchVal1[1] = pchVal2[2];
|
||||
pchVal1[2] = pchVal2[1];
|
||||
pchVal1[3] = pchVal2[0];
|
||||
}
|
||||
|
||||
void System::ReverseULONGLONG(int64_t* pullVal) {
|
||||
int64_t ullValue = *pullVal;
|
||||
unsigned char* pchVal1 = (unsigned char*)pullVal;
|
||||
unsigned char* pchVal2 = (unsigned char*)&ullValue;
|
||||
|
||||
pchVal1[0] = pchVal2[7];
|
||||
pchVal1[1] = pchVal2[6];
|
||||
pchVal1[2] = pchVal2[5];
|
||||
pchVal1[3] = pchVal2[4];
|
||||
pchVal1[4] = pchVal2[3];
|
||||
pchVal1[5] = pchVal2[2];
|
||||
pchVal1[6] = pchVal2[1];
|
||||
pchVal1[7] = pchVal2[0];
|
||||
}
|
||||
|
||||
void System::ReverseWCHARA(wchar_t* pwch, int iLen) {
|
||||
for (int i = 0; i < iLen; i++) {
|
||||
ReverseUSHORT((unsigned short*)&pwch[i]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user