mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
Fix full URL skins for non-humanoid disappearing when changing model of an entity
This commit is contained in:
parent
c8b081f348
commit
ab9fe3c14f
@ -16,20 +16,10 @@ namespace ClassicalSharp.Entities {
|
||||
anim = new AnimatedComponent(game, this);
|
||||
}
|
||||
|
||||
/// <summary> The model of this entity. (used for collision detection and rendering) </summary>
|
||||
public IModel Model;
|
||||
|
||||
/// <summary> The name of the model of this entity. </summary>
|
||||
public string ModelName;
|
||||
|
||||
/// <summary> BlockID if model name is a vaid block id. </summary>
|
||||
/// <remarks> This avoids needing to repeatedly parse ModelName as a byte. </remarks>
|
||||
public string SkinName, ModelName;
|
||||
public BlockID ModelBlock;
|
||||
|
||||
/// <summary> Scale applied to the model for collision detection and rendering. </summary>
|
||||
public Vector3 ModelScale = new Vector3(1.0f);
|
||||
|
||||
/// <summary> Returns the size of the model that is used for collision detection. </summary>
|
||||
public Vector3 Size;
|
||||
|
||||
public int TextureId, MobTextureId;
|
||||
@ -132,6 +122,10 @@ namespace ClassicalSharp.Entities {
|
||||
ParseScale(scale);
|
||||
Model.RecalcProperties(this);
|
||||
UpdateModelBounds();
|
||||
|
||||
if (SkinName != null && Utils.IsUrlPrefix(SkinName, 0)) {
|
||||
MobTextureId = TextureId;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateModelBounds() {
|
||||
|
@ -14,7 +14,7 @@ namespace ClassicalSharp.Entities {
|
||||
|
||||
public abstract class Player : Entity {
|
||||
|
||||
public string DisplayName, SkinName;
|
||||
public string DisplayName;
|
||||
protected Texture nameTex;
|
||||
internal bool fetchedSkin;
|
||||
|
||||
|
@ -91,7 +91,7 @@ static ReturnCode Sound_ReadWaveData(struct Stream* stream, struct Sound* snd) {
|
||||
snd->Format.BitsPerSample = Stream_GetU16_LE(&tmp[14]);
|
||||
size -= WAV_FMT_SIZE;
|
||||
} else if (fourCC == WAV_FourCC('d','a','t','a')) {
|
||||
snd->Data = Mem_Alloc(size, sizeof(UInt8), "WAV sound data");
|
||||
snd->Data = Mem_Alloc(size, 1, "WAV sound data");
|
||||
snd->DataSize = size;
|
||||
return Stream_Read(stream, snd->Data, size);
|
||||
}
|
||||
@ -498,8 +498,9 @@ static Int32 AudioManager_GetVolume(const char* volKey, const char* boolKey) {
|
||||
return volume;
|
||||
}
|
||||
|
||||
static void AudioManager_FilesCallback(const String* filename, void* obj) {
|
||||
StringsBuffer_Add(&files, filename);
|
||||
static void AudioManager_FilesCallback(const String* path, void* obj) {
|
||||
String file = *path; Utils_UNSAFE_GetFilename(&file);
|
||||
StringsBuffer_Add(&files, &file);
|
||||
}
|
||||
|
||||
static void AudioManager_Init(void) {
|
||||
|
67
src/Entity.c
67
src/Entity.c
@ -72,6 +72,7 @@ void Entity_Init(struct Entity* e) {
|
||||
e->ModelScale = Vector3_Create1(1.0f);
|
||||
e->uScale = 1.0f;
|
||||
e->vScale = 1.0f;
|
||||
e->SkinNameRaw[0] = '\0';
|
||||
}
|
||||
|
||||
Vector3 Entity_GetEyePosition(struct Entity* e) {
|
||||
@ -153,6 +154,8 @@ void Entity_SetModel(struct Entity* e, const String* model) {
|
||||
e->Model->RecalcProperties(e);
|
||||
Entity_UpdateModelBounds(e);
|
||||
|
||||
String skin = String_FromRawArray(e->SkinNameRaw);
|
||||
if (Utils_IsUrlPrefix(&skin, 0)) { e->MobTextureId = e->TextureId; }
|
||||
}
|
||||
|
||||
void Entity_UpdateModelBounds(struct Entity* e) {
|
||||
@ -546,14 +549,15 @@ static void Player_DrawName(struct Player* player) {
|
||||
|
||||
static struct Player* Player_FirstOtherWithSameSkin(struct Player* player) {
|
||||
struct Entity* entity = &player->Base;
|
||||
String skin = String_FromRawArray(player->SkinNameRaw);
|
||||
String skin = String_FromRawArray(entity->SkinNameRaw);
|
||||
Int32 i;
|
||||
|
||||
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
|
||||
if (!Entities_List[i] || Entities_List[i] == entity) continue;
|
||||
if (Entities_List[i]->EntityType != ENTITY_TYPE_PLAYER) continue;
|
||||
|
||||
struct Player* p = (struct Player*)Entities_List[i];
|
||||
String pSkin = String_FromRawArray(p->SkinNameRaw);
|
||||
String pSkin = String_FromRawArray(p->Base.SkinNameRaw);
|
||||
if (String_Equals(&skin, &pSkin)) return p;
|
||||
}
|
||||
return NULL;
|
||||
@ -561,14 +565,15 @@ static struct Player* Player_FirstOtherWithSameSkin(struct Player* player) {
|
||||
|
||||
static struct Player* Player_FirstOtherWithSameSkinAndFetchedSkin(struct Player* player) {
|
||||
struct Entity* entity = &player->Base;
|
||||
String skin = String_FromRawArray(player->SkinNameRaw);
|
||||
String skin = String_FromRawArray(entity->SkinNameRaw);
|
||||
Int32 i;
|
||||
|
||||
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
|
||||
if (!Entities_List[i] || Entities_List[i] == entity) continue;
|
||||
if (Entities_List[i]->EntityType != ENTITY_TYPE_PLAYER) continue;
|
||||
|
||||
struct Player* p = (struct Player*)Entities_List[i];
|
||||
String pSkin = String_FromRawArray(p->SkinNameRaw);
|
||||
String pSkin = String_FromRawArray(p->Base.SkinNameRaw);
|
||||
if (p->FetchedSkin && String_Equals(&skin, &pSkin)) return p;
|
||||
}
|
||||
return NULL;
|
||||
@ -585,10 +590,8 @@ static void Player_ApplySkin(struct Player* player, struct Player* from) {
|
||||
|
||||
/* Custom mob textures */
|
||||
dst->MobTextureId = NULL;
|
||||
String skin = String_FromRawArray(player->SkinNameRaw);
|
||||
if (Utils_IsUrlPrefix(&skin, 0)) {
|
||||
dst->MobTextureId = dst->TextureId;
|
||||
}
|
||||
String skin = String_FromRawArray(dst->SkinNameRaw);
|
||||
if (Utils_IsUrlPrefix(&skin, 0)) { dst->MobTextureId = dst->TextureId; }
|
||||
}
|
||||
|
||||
void Player_ResetSkin(struct Player* player) {
|
||||
@ -601,14 +604,16 @@ void Player_ResetSkin(struct Player* player) {
|
||||
|
||||
/* Apply or reset skin, for all players with same skin */
|
||||
static void Player_SetSkinAll(struct Player* player, bool reset) {
|
||||
String skin = String_FromRawArray(player->SkinNameRaw);
|
||||
struct Entity* entity = &player->Base;
|
||||
String skin = String_FromRawArray(entity->SkinNameRaw);
|
||||
Int32 i;
|
||||
|
||||
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
|
||||
if (!Entities_List[i]) continue;
|
||||
if (Entities_List[i]->EntityType != ENTITY_TYPE_PLAYER) continue;
|
||||
|
||||
struct Player* p = (struct Player*)Entities_List[i];
|
||||
String pSkin = String_FromRawArray(p->SkinNameRaw);
|
||||
String pSkin = String_FromRawArray(p->Base.SkinNameRaw);
|
||||
if (!String_Equals(&skin, &pSkin)) continue;
|
||||
|
||||
if (reset) {
|
||||
@ -670,23 +675,23 @@ static void Player_EnsurePow2(struct Player* player, Bitmap* bmp) {
|
||||
*bmp = scaled;
|
||||
}
|
||||
|
||||
static void Player_CheckSkin(struct Player* player) {
|
||||
struct Entity* entity = &player->Base;
|
||||
String skin = String_FromRawArray(player->SkinNameRaw);
|
||||
static void Player_CheckSkin(struct Player* p) {
|
||||
struct Entity* e = &p->Base;
|
||||
String skin = String_FromRawArray(e->SkinNameRaw);
|
||||
|
||||
if (!player->FetchedSkin && entity->Model->UsesSkin) {
|
||||
struct Player* first = Player_FirstOtherWithSameSkinAndFetchedSkin(player);
|
||||
if (!p->FetchedSkin && e->Model->UsesSkin) {
|
||||
struct Player* first = Player_FirstOtherWithSameSkinAndFetchedSkin(p);
|
||||
if (!first) {
|
||||
AsyncDownloader_GetSkin(&skin, &skin);
|
||||
} else {
|
||||
Player_ApplySkin(player, first);
|
||||
Player_ApplySkin(p, first);
|
||||
}
|
||||
player->FetchedSkin = true;
|
||||
p->FetchedSkin = true;
|
||||
}
|
||||
|
||||
struct AsyncRequest item;
|
||||
if (!AsyncDownloader_Get(&skin, &item)) return;
|
||||
if (!item.ResultData) { Player_SetSkinAll(player, true); return; }
|
||||
if (!item.ResultData) { Player_SetSkinAll(p, true); return; }
|
||||
|
||||
String url = String_FromRawArray(item.URL);
|
||||
struct Stream mem; Bitmap bmp;
|
||||
@ -698,19 +703,19 @@ static void Player_CheckSkin(struct Player* player) {
|
||||
Mem_Free(bmp.Scan0); return;
|
||||
}
|
||||
|
||||
Gfx_DeleteTexture(&entity->TextureId);
|
||||
Player_SetSkinAll(player, true);
|
||||
Player_EnsurePow2(player, &bmp);
|
||||
entity->SkinType = Utils_GetSkinType(&bmp);
|
||||
Gfx_DeleteTexture(&e->TextureId);
|
||||
Player_SetSkinAll(p, true);
|
||||
Player_EnsurePow2(p, &bmp);
|
||||
e->SkinType = Utils_GetSkinType(&bmp);
|
||||
|
||||
if (entity->SkinType == SKIN_INVALID) {
|
||||
Player_SetSkinAll(player, true);
|
||||
if (e->SkinType == SKIN_INVALID) {
|
||||
Player_SetSkinAll(p, true);
|
||||
} else {
|
||||
if (entity->Model->UsesHumanSkin) {
|
||||
Player_ClearHat(&bmp, entity->SkinType);
|
||||
if (e->Model->UsesHumanSkin) {
|
||||
Player_ClearHat(&bmp, e->SkinType);
|
||||
}
|
||||
entity->TextureId = Gfx_CreateTexture(&bmp, true, false);
|
||||
Player_SetSkinAll(player, false);
|
||||
e->TextureId = Gfx_CreateTexture(&bmp, true, false);
|
||||
Player_SetSkinAll(p, false);
|
||||
}
|
||||
Mem_Free(bmp.Scan0);
|
||||
}
|
||||
@ -736,10 +741,10 @@ static void Player_ContextRecreated(struct Entity* e) {
|
||||
Player_UpdateNameTex(player);
|
||||
}
|
||||
|
||||
void Player_SetName(struct Player* player, const String* name, const String* skin) {
|
||||
String p_name = String_ClearedArray(player->DisplayNameRaw);
|
||||
void Player_SetName(struct Player* p, const String* name, const String* skin) {
|
||||
String p_name = String_ClearedArray(p->DisplayNameRaw);
|
||||
String_AppendString(&p_name, name);
|
||||
String p_skin = String_ClearedArray(player->SkinNameRaw);
|
||||
String p_skin = String_ClearedArray(p->Base.SkinNameRaw);
|
||||
String_AppendString(&p_skin, skin);
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ struct Entity {
|
||||
struct Matrix Transform;
|
||||
|
||||
struct AnimatedComp Anim;
|
||||
char SkinNameRaw[STRING_SIZE];
|
||||
};
|
||||
|
||||
void Entity_Init(struct Entity* entity);
|
||||
@ -126,7 +127,7 @@ void TabList_MakeComponent(struct IGameComponent* comp);
|
||||
#define TabList_UNSAFE_GetPlayer(id) StringsBuffer_UNSAFE_Get(&TabList_Buffer, TabList_PlayerNames[id]);
|
||||
#define TabList_UNSAFE_GetList(id) StringsBuffer_UNSAFE_Get(&TabList_Buffer, TabList_ListNames[id]);
|
||||
#define TabList_UNSAFE_GetGroup(id) StringsBuffer_UNSAFE_Get(&TabList_Buffer, TabList_GroupNames[id]);
|
||||
#define Player_Layout struct Entity Base; char DisplayNameRaw[STRING_SIZE]; char SkinNameRaw[STRING_SIZE]; bool FetchedSkin; struct Texture NameTex;
|
||||
#define Player_Layout struct Entity Base; char DisplayNameRaw[STRING_SIZE]; bool FetchedSkin; struct Texture NameTex;
|
||||
|
||||
/* Represents a player entity. */
|
||||
struct Player { Player_Layout };
|
||||
|
@ -308,7 +308,7 @@ static ReturnCode Nbt_ReadTag(UInt8 typeId, bool readTagName, struct Stream* str
|
||||
if (tag.DataSize < NBT_SMALL_SIZE) {
|
||||
res = Stream_Read(stream, tag.DataSmall, tag.DataSize);
|
||||
} else {
|
||||
tag.DataBig = Mem_Alloc(tag.DataSize, sizeof(UInt8), "NBT data");
|
||||
tag.DataBig = Mem_Alloc(tag.DataSize, 1, "NBT data");
|
||||
res = Stream_Read(stream, tag.DataBig, tag.DataSize);
|
||||
if (res) { Mem_Free(tag.DataBig); }
|
||||
}
|
||||
@ -719,7 +719,7 @@ static ReturnCode Dat_ReadFieldData(struct Stream* stream, struct JFieldDesc* fi
|
||||
if ((res = Stream_ReadU32_BE(stream, &count))) return res;
|
||||
field->Value_Size = count;
|
||||
|
||||
field->Value_Ptr = Mem_Alloc(count, sizeof(UInt8), ".dat map blocks");
|
||||
field->Value_Ptr = Mem_Alloc(count, 1, ".dat map blocks");
|
||||
res = Stream_Read(stream, field->Value_Ptr, count);
|
||||
if (res) { Mem_Free(field->Value_Ptr); return res; }
|
||||
} break;
|
||||
|
20
src/Menus.c
20
src/Menus.c
@ -1399,10 +1399,12 @@ static void TexturePackScreen_EntryClick(void* screen, void* widget) {
|
||||
ListScreen_SetCurrentIndex(s, idx);
|
||||
}
|
||||
|
||||
static void TexturePackScreen_FilterFiles(const String* filename, void* obj) {
|
||||
static void TexturePackScreen_FilterFiles(const String* path, void* obj) {
|
||||
String zip = String_FromConst(".zip");
|
||||
if (!String_CaselessEnds(filename, &zip)) return;
|
||||
StringsBuffer_Add((StringsBuffer*)obj, filename);
|
||||
if (!String_CaselessEnds(path, &zip)) return;
|
||||
|
||||
String file = *path; Utils_UNSAFE_GetFilename(&file);
|
||||
StringsBuffer_Add((StringsBuffer*)obj, &file);
|
||||
}
|
||||
|
||||
struct Screen* TexturePackScreen_MakeInstance(void) {
|
||||
@ -1545,13 +1547,15 @@ struct Screen* HotkeyListScreen_MakeInstance(void) {
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------LoadLevelScreen------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void LoadLevelScreen_FilterFiles(const String* filename, void* obj) {
|
||||
String cw = String_FromConst(".cw"); String lvl = String_FromConst(".lvl");
|
||||
static void LoadLevelScreen_FilterFiles(const String* path, void* obj) {
|
||||
String cw = String_FromConst(".cw"); String lvl = String_FromConst(".lvl");
|
||||
String fcm = String_FromConst(".fcm"); String dat = String_FromConst(".dat");
|
||||
|
||||
if (!(String_CaselessEnds(filename, &cw) || String_CaselessEnds(filename, &lvl)
|
||||
|| String_CaselessEnds(filename, &fcm) || String_CaselessEnds(filename, &dat))) return;
|
||||
StringsBuffer_Add((StringsBuffer*)obj, filename);
|
||||
if (!(String_CaselessEnds(path, &cw) || String_CaselessEnds(path, &lvl)
|
||||
|| String_CaselessEnds(path, &fcm) || String_CaselessEnds(path, &dat))) return;
|
||||
|
||||
String file = *path; Utils_UNSAFE_GetFilename(&file);
|
||||
StringsBuffer_Add((StringsBuffer*)obj, &file);
|
||||
}
|
||||
|
||||
void LoadLevelScreen_LoadMap(const String* path) {
|
||||
|
@ -306,28 +306,27 @@ bool File_Exists(const String* path) {
|
||||
return attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
ReturnCode Directory_Enum(const String* path, void* obj, Directory_EnumCallback callback) {
|
||||
char fileBuffer[MAX_PATH + 10];
|
||||
String file = String_FromArray(fileBuffer);
|
||||
ReturnCode Directory_Enum(const String* dirPath, void* obj, Directory_EnumCallback callback) {
|
||||
char pathBuffer[MAX_PATH + 10];
|
||||
String path = String_FromArray(pathBuffer);
|
||||
/* Need to append \* to search for files in directory */
|
||||
String_Format1(&file, "%s\\*", path);
|
||||
WCHAR str[300]; Platform_ConvertString(str, &file);
|
||||
String_Format1(&path, "%s\\*", dirPath);
|
||||
WCHAR str[300]; Platform_ConvertString(str, &path);
|
||||
|
||||
WIN32_FIND_DATAW entry;
|
||||
HANDLE find = FindFirstFileW(str, &entry);
|
||||
if (find == INVALID_HANDLE_VALUE) return GetLastError();
|
||||
|
||||
do {
|
||||
if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
||||
file.length = 0;
|
||||
if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
||||
path.length = 0;
|
||||
String_Format2(&path, "%s%r", dirPath, &Directory_Separator);
|
||||
Int32 i;
|
||||
|
||||
for (i = 0; i < MAX_PATH && entry.cFileName[i]; i++) {
|
||||
String_Append(&file, Convert_UnicodeToCP437(entry.cFileName[i]));
|
||||
String_Append(&path, Convert_UnicodeToCP437(entry.cFileName[i]));
|
||||
}
|
||||
|
||||
Utils_UNSAFE_GetFilename(&file);
|
||||
callback(&file, obj);
|
||||
callback(&path, obj);
|
||||
} while (FindNextFileW(find, &entry));
|
||||
|
||||
ReturnCode result = GetLastError(); /* return code from FindNextFile */
|
||||
@ -418,27 +417,25 @@ bool File_Exists(const String* path) {
|
||||
return stat(str, &sb) == 0 && S_ISREG(sb.st_mode);
|
||||
}
|
||||
|
||||
ReturnCode Directory_Enum(const String* path, void* obj, Directory_EnumCallback callback) {
|
||||
char str[600]; Platform_ConvertString(str, path);
|
||||
ReturnCode Directory_Enum(const String* dirPath, void* obj, Directory_EnumCallback callback) {
|
||||
char str[600]; Platform_ConvertString(str, dirPath);
|
||||
DIR* dirPtr = opendir(str);
|
||||
if (!dirPtr) return errno;
|
||||
|
||||
char fileBuffer[FILENAME_SIZE];
|
||||
String file = String_FromArray(fileBuffer);
|
||||
char pathBuffer[FILENAME_SIZE];
|
||||
String path = String_FromArray(pathBuffer);
|
||||
struct dirent* entry;
|
||||
|
||||
/* TODO: does this also include subdirectories */
|
||||
while (entry = readdir(dirPtr)) {
|
||||
UInt16 len = String_CalcLen(entry->d_name, UInt16_MaxValue);
|
||||
file.length = 0;
|
||||
String_DecodeUtf8(&file, entry->d_name, len);
|
||||
path.length = 0;
|
||||
String_DecodeUtf8(&path, entry->d_name, len);
|
||||
|
||||
/* exlude . and .. paths */
|
||||
if (file.length == 1 && file.buffer[0] == '.') continue;
|
||||
if (file.length == 2 && file.buffer[0] == '.' && file.buffer[1] == '.') continue;
|
||||
|
||||
Utils_UNSAFE_GetFilename(&file);
|
||||
callback(&file, obj);
|
||||
if (path.length == 1 && path.buffer[0] == '.') continue;
|
||||
if (path.length == 2 && path.buffer[0] == '.' && path.buffer[1] == '.') continue;
|
||||
callback(&path, obj);
|
||||
}
|
||||
|
||||
int result = errno; /* return code from readdir */
|
||||
@ -734,12 +731,10 @@ void Font_Free(FontDesc* desc) {
|
||||
desc->Handle = NULL;
|
||||
}
|
||||
|
||||
static void Font_DirCallback(const String* filename, void* obj) {
|
||||
static void Font_DirCallback(const String* srcPath, void* obj) {
|
||||
char pathBuffer[FILENAME_SIZE + 1];
|
||||
String path = String_NT_Array(pathBuffer);
|
||||
String* dir = obj;
|
||||
|
||||
String_Format2(&path, "%s%s", dir, filename);
|
||||
String_Copy(&path, srcPath);
|
||||
path.buffer[path.length] = '\0';
|
||||
|
||||
FT_Face face;
|
||||
@ -828,8 +823,8 @@ Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, Int32 x, Int32
|
||||
#if CC_BUILD_WIN
|
||||
static void Font_Init(void) {
|
||||
FT_Error err = FT_Init_FreeType(&lib);
|
||||
String dir = String_FromConst("C:\\Windows\\fonts\\");
|
||||
Directory_Enum(&dir, &dir, Font_DirCallback);
|
||||
String dir = String_FromConst("C:\\Windows\\fonts");
|
||||
Directory_Enum(&dir, NULL, Font_DirCallback);
|
||||
}
|
||||
#elif CC_BUILD_NIX
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user