mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
Fixed an issue with JS Function DeleteFile(), which would stop calling script from working if no file was found for deletion. Could break demolishing of houses, amongst other things Fixed an issue with DoSEErrorMessage() function that prevented JS function error messages from being displayed in UOX3 console if message size was below 512 Fixed a bug that allowed players to place items on the same slot of walls when using a client that doesn't automatically restrict this When dropping items, UOX3 will now look for a valid surface to drop them on, and move the item to said valid surface if applicable Fixed an issue with loading of MultiCollections.uop where max boundaries of each multi was not set on load, preventing features that relied on finding corners of building from working (like automatic ban location detection for houses) Added new function in mapstuff.cpp to check flags on dynamic items, and exposed it as a JS Function with same name and parameters: CheckDynamicFlag( SI16 x, SI16 y, SI08 oldz, UI08 worldNumber, UI16 instanceID, TileFlags toCheck ); Fixed an issue where items were not always properly added to/removed from map regions when picked up or dropped Added new helper function in dist.cpp to find 3D distance between two points: getDist3D( point a, point b ) Added JS Function - DistanceBetween() - to find distance between two sets of coordinates, or two objects: DistanceBetween( x1, y1, x2, y2 ) DistanceBetween( x1, y1, z1, x2, y2, z2 ) DistanceBetween( sourceObject, targObject ) DistanceBetween( sourceObject, targObject, checkZ ) Added Item JS Method - GetTileName() - to get name of an item directly from tiledata Added new UOX.INI setting that defines the lower limit for when a purchase will withdraw money from bank instead of backpack: BANKBUYTHRESHOLD=2000 Split the UOX.INI setting CONSOLELOG into three parts, to enable/disable different forms of logging: CONSOLELOG=1/0 // Toggles logging of console messages, warnings and errors NETWORKLOG=1/0 // Toggles logging of network traffic SPEECHLOG=1/0 // Toggles logging of player/staff speech
226 lines
6.6 KiB
C++
226 lines
6.6 KiB
C++
//
|
|
// Created on: 4/30/21
|
|
|
|
#include "MultiMul.hpp"
|
|
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <fstream>
|
|
#include <filesystem>
|
|
#include <algorithm>
|
|
|
|
#include "IDXMul.hpp"
|
|
|
|
using namespace UO ;
|
|
|
|
const std::string MultiMul::_uopformat = "build/multicollection/%06d.bin";
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Methods for MultiMul
|
|
//
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//=========================================================================
|
|
std::size_t multi_structure::memoryComponent() const {
|
|
std::size_t rvalue = 0 ;
|
|
for (auto &entry : _items) {
|
|
rvalue = rvalue + entry.second.size() * sizeof(multi_component) ;
|
|
}
|
|
return rvalue ;
|
|
}
|
|
|
|
|
|
//=========================================================================
|
|
MultiMul::MultiMul() : UOPData() {
|
|
_mytype = UOPData::multi ;
|
|
_hashformat = _uopformat;
|
|
_maxhashes = 0x10000 ;
|
|
}
|
|
//=========================================================================
|
|
MultiMul::MultiMul(const std::string &mulpath, const std::string &idxpath):MultiMul() {
|
|
|
|
load(mulpath,idxpath);
|
|
}
|
|
//=========================================================================
|
|
MultiMul::MultiMul(const std::string &uoppath) : MultiMul() {
|
|
load(uoppath);
|
|
}
|
|
//=============================================================================
|
|
void MultiMul::load(const std::string &uoppath){
|
|
std::ifstream uopstream(uoppath,std::ifstream::binary|std::ifstream::in);
|
|
if (!uopstream.is_open()){
|
|
throw std::runtime_error(std::string("Unable to open uop file: ")+uoppath);
|
|
}
|
|
loadUOP(uopstream);
|
|
uopstream.close();
|
|
|
|
}
|
|
|
|
//=============================================================================
|
|
void MultiMul::processData(std::vector<unsigned char> &data, std::uint32_t chunkid){
|
|
multi_structure structure ;
|
|
std::size_t offset = 4 ; // skip the first 32 bit word
|
|
std::uint32_t count ;
|
|
count = (*reinterpret_cast<std::uint32_t *>((data.data()+offset))) ;
|
|
offset = offset + 4 ;
|
|
for (unsigned int i = 0 ; i < count ; i++){
|
|
multi_component component ;
|
|
component.visible = 0 ;
|
|
component.tileid = (*reinterpret_cast<std::uint16_t *>((data.data()+offset))) ;
|
|
offset = offset + 2 ;
|
|
component.xoffset = (*reinterpret_cast<std::int16_t *>((data.data()+offset))) ;
|
|
offset = offset + 2 ;
|
|
component.yoffset = (*reinterpret_cast<std::int16_t *>((data.data()+offset))) ;
|
|
offset = offset + 2 ;
|
|
component.zoffset = (*reinterpret_cast<std::int16_t *>((data.data()+offset))) ;
|
|
offset = offset + 2 ;
|
|
auto flags = (*reinterpret_cast<std::uint16_t *>((data.data()+offset))) ;
|
|
offset = offset + 2 ;
|
|
switch (flags) {
|
|
default:
|
|
case 0: // background
|
|
component.visible = 1 ;
|
|
break;
|
|
case 1: // none
|
|
break;
|
|
case 257: // generic
|
|
component.visible = 0x800;
|
|
break;
|
|
}
|
|
auto clilocs = (*reinterpret_cast<std::uint32_t *>((data.data()+offset))) ;
|
|
offset = offset + 4 ;
|
|
if (clilocs != 0 ) {
|
|
offset = offset + (clilocs * 4);
|
|
}
|
|
|
|
// Add max bounds of multi
|
|
structure._maxX = std::max( static_cast<int>( component.xoffset ), structure._maxX );
|
|
structure._minX = std::min( static_cast<int>( component.xoffset ), structure._minX );
|
|
structure._maxY = std::max( static_cast<int>( component.yoffset ), structure._maxY );
|
|
structure._minY = std::min( static_cast<int>( component.yoffset ), structure._minY );
|
|
|
|
structure.addItem(component);
|
|
|
|
}
|
|
_entries.insert_or_assign(chunkid, structure);
|
|
}
|
|
|
|
|
|
//=========================================================================
|
|
void MultiMul::load(const std::string &mulpath, const std::string &idxpath){
|
|
|
|
bool useHS = false ;
|
|
|
|
auto mulsize = std::filesystem::file_size(std::filesystem::path(mulpath));
|
|
if (mulsize >= hssize) {
|
|
useHS = true ;
|
|
}
|
|
auto idx = IDXMul(idxpath);
|
|
auto size = idx.size() ;
|
|
std::ifstream mul(mulpath, std::ios::binary | std::ios::in);
|
|
if (!mul.is_open()) {
|
|
throw std::runtime_error(std::string("Unable to open: ")+ mulpath) ;
|
|
}
|
|
for ( auto i = 0 ; i < size ; i++) {
|
|
auto entry = idx[i] ;
|
|
if (entry.valid()) {
|
|
mul.seekg(entry.offset,std::ios::beg) ;
|
|
auto length = entry.length ;
|
|
multi_structure entry= multi_structure();
|
|
bool firsttime = true ;
|
|
while (length > 0) {
|
|
multi_component item ;
|
|
|
|
short temp =0;
|
|
unsigned int dummy =0;
|
|
// Read in Tileid
|
|
mul.read(reinterpret_cast<char*>(&temp),2);
|
|
item.tileid = static_cast<unsigned short>(temp);
|
|
length = length-2 ;
|
|
|
|
// Read in xoffset
|
|
mul.read(reinterpret_cast<char*>(&temp),2);
|
|
item.xoffset = static_cast<unsigned short>(temp);
|
|
length = length-2 ;
|
|
|
|
// Read in yoffset
|
|
mul.read(reinterpret_cast<char*>(&temp),2);
|
|
item.yoffset = static_cast<unsigned short>(temp);
|
|
length = length-2 ;
|
|
|
|
// Read in Zoffset
|
|
mul.read(reinterpret_cast<char*>(&temp),2);
|
|
item.zoffset = static_cast<unsigned short>(temp);
|
|
length = length-2 ;
|
|
|
|
// Read in flags ;
|
|
mul.read(reinterpret_cast<char*>(&dummy),4);
|
|
item.visible = dummy ;
|
|
length = length-4 ;
|
|
if (useHS) {
|
|
mul.read(reinterpret_cast<char*>(&dummy),4);
|
|
length = length-4;
|
|
|
|
}
|
|
|
|
if (firsttime) {
|
|
entry._maxX = item.xoffset ;
|
|
entry._minX = item.xoffset ;
|
|
entry._maxY = item.yoffset ;
|
|
entry._minY = item.yoffset;
|
|
firsttime = false;
|
|
}
|
|
else {
|
|
|
|
entry._maxX = std::max(static_cast<int>(item.xoffset),entry._maxX);
|
|
entry._minX = std::min(static_cast<int>(item.xoffset),entry._minX);
|
|
entry._maxY = std::max(static_cast<int>(item.yoffset),entry._maxY);
|
|
entry._minY = std::min(static_cast<int>(item.yoffset),entry._minY);
|
|
}
|
|
|
|
entry.addItem(item);
|
|
}
|
|
|
|
_entries.insert_or_assign(i, entry);
|
|
|
|
}
|
|
}
|
|
}
|
|
//======================================================================
|
|
bool MultiMul::exists(int id){
|
|
auto iter = _entries.find(id) ;
|
|
if (iter == _entries.end()) {
|
|
return false ;
|
|
}
|
|
return true ;
|
|
|
|
}
|
|
//======================================================================
|
|
const multi_structure& MultiMul::entry(int id) const {
|
|
auto iter = _entries.find(id) ;
|
|
if (iter != _entries.end()) {
|
|
return iter->second ;
|
|
}
|
|
else {
|
|
throw std::runtime_error(std::string("Multi id: ") + std::to_string(id) + std::string(" not found"));
|
|
}
|
|
}
|
|
//======================================================================
|
|
std::size_t MultiMul::amount() const {
|
|
return _entries.size() ;
|
|
}
|
|
|
|
//======================================================================
|
|
std::size_t MultiMul::memoryMulti() const {
|
|
std::size_t rvalue = 0 ;
|
|
for (auto &entry : _entries) {
|
|
rvalue = rvalue + entry.second.memoryComponent() ;
|
|
}
|
|
return rvalue ;
|
|
}
|
|
|
|
//======================================================================
|
|
std::size_t MultiMul::size() const {
|
|
return _entries.size() ;
|
|
}
|