• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ - Pobranie najwyższego kontenera (containers.cpp)

MeNi

*^#%$%
Joined
Jul 23, 2008
Messages
183
Reaction score
12
Pisze jeszcze raz w nowym temacie, bo tamten dotyczyl czegos innego, poza tym pytanie zaginelo gdzies w n-tym poscie.

mam taką funkcję w kodzie TFSa (container.cpp), która ma sprawdzać, czy można dodać coś do danego np. BP:

Code:
ReturnValue Container::__queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const
{
// (...)
}
i chcę z jej wnętrza pobrać do zmiennej np. const Container* topParent najwyższy bp/inny container, w którym znajduje się container, do którego dodajemy item, aby potem wywołać getItemHoldingCount() i zliczyć wszystkie przedmioty, które są w całej gałęzi backpacków/innych kontenerów, zaczynając od piewrwszego.

Przykład

BP0: [item,item,BP1,item,item]
BR1: [item,BP2]
BP2: [item,item,BP3]
BP3: [item]

i powiedzmy, że wkładam przedmiot do BP2. Wywoływane jest Container::__queryAdd dla BP2, i jeśli użyję tutaj getItemHoldingCount() to zliczy tylko itemy z BP2 i BP3, dlatego chcę pobrać do zmiennej topParent BP0 i dla niego uruchomić topParent->getItemHoldingCount() żeby zliczyć wszystkie przedmioty (BP0,BP1,BP2,BP3)

Próbowałem w następujący sposób:

Code:
ReturnValue Container::__queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const
{
(...)
const Cylinder* topParent = getTopParent();

if(topParent->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;
}

ale getTopParent() zwraca Cylinder* (nutaj nie wiem, czym różni się on od Container* i do czego służy, bo w niektórych miejscach w kodzie jest do niego porównywany, wiec jest to coś podobnego do Container* prawdopodobnie)

próbowałem tak:
Code:
ReturnValue Container::__queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const
{
(...)
Container* topParent = this;
while (topParent->getParentContainer())
{
	topParent = topParent->getParentContainer();
}

if(topParent->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;

wtedy mam błąd:

Code:
~source\container.cpp invalid conversion from `const Container* const' to `Container*'

Jakieś pomysły, jak to zrobić?
 
hi,

Code:
const Container* topParent = dynamic_cast<const Container*>(getTopParent());
if(topParent->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;

bye...
 
hi,

Code:
const Container* topParent = dynamic_cast<const Container*>(getTopParent());
if(topParent->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;

bye...


Przy zastosowaniu dynamic casta ta linijka crashuje serwer:
Code:
topParent->getItemHoldingCount();
 
ehh...

Code:
const Container* aux = dynamic_cast<const Container*>(getParent());
if(aux)
{
	const Container* prev = this;
	while(aux->getParent())
	{
		prev = aux;
		aux = dynamic_cast<const Container*>(aux->getParent());
	}

	if(dynamic_cast<const Container*>(prev))
		aux = aux;
}
else
	aux = this;

if(aux && aux->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;
 
ehh...

Code:
const Container* aux = dynamic_cast<const Container*>(getParent());
if(aux)
{
	const Container* prev = this;
	while(aux->getParent())
	{
		prev = aux;
		aux = dynamic_cast<const Container*>(aux->getParent());
	}

	if(dynamic_cast<const Container*>(prev))
		aux = aux;
}
else
	aux = this;

if(aux && aux->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;


hmm, teraz crash nastepuje w sytuacji, gdy wkładasz przedmiot do BP, który jest w innym BP.

Przy okazji, jak sprawdzić przyczynę crasha pod windowsem?
 
ech, nie chce mi sie tego sprawdzac. dalem ci rozwiazanie- zerknij na thing.h i pobaw się.
ogólnie to chyba niepotrzebnie rzucam dynamic_casty, wystarczy cylinder->getItem.
 
ten kod działa, ale trzeba go wsadzić do Container::__addThing:

Code:
	int32_t addCount = 0;
	
	if(const Container* container = item->getContainer())
		addCount = container->getItemHoldingCount() + 1;
	else
		addCount = 1;
	
[B]	Container* topContainer = this;
	while (topContainer->getParentContainer())
	{
		topContainer = topContainer->getParentContainer();
	}[/B]
	
	std::clog << "[__AddThing] HoldingCount: " << topContainer->getItemHoldingCount() << ", AddCount: " << addCount << ", MaxCount: " << g_config.getNumber(ConfigManager::MAX_ITEM_COUNT) << std::endl;
	if(topContainer->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
		return /*RET_THISISIMPOSSIBLE*/;

I cały problem w tym, że __addThing jest wywoływane jak item, który przenosimy został już usunięty, i ma zostać dodany w nowe miejsce, wiec jak w nowym BP będzie za dużo itemów, to return; spowoduje, że item się nie doda w nowe miejsce, a w starym już go nie ma, więc zniknie, co może byc "trochę" wkurzające.
Za to w Container::__queryAdd, które ma za zadanie sprawdzać, czy można przenieść item jeszcze przed skasowaniem go ze starego miesjca, nie pozwala zadeklarować Container* topContainer = this; bez const na początku, więc kod podany wyżej nie przejdzie...
 
jakbys przeanalizował mój kod, wiedziałbyś, że w swoim kodzie masz zdefiniować:
Code:
const Container* topContainer = this;
a nie:
Code:
Container* topContainer = this;
 
ehh...

Code:
const Container* aux = dynamic_cast<const Container*>(getParent());
if(aux)
{
	const Container* prev = this;
	while(aux->getParent())
	{
		prev = aux;
		aux = dynamic_cast<const Container*>(aux->getParent());
	}

	if(dynamic_cast<const Container*>(prev))
		aux = aux;
}
else
	aux = this;

if(aux && aux->getItemHoldingCount() + addCount > g_config.getNumber(ConfigManager::MAX_ITEM_COUNT))
	return RET_THISISIMPOSSIBLE;

Jaki jest cel tej:
Code:
const Container* prev = this;
zmiennej?

Co to:
Code:
if(dynamic_cast<const Container*>(prev))
	aux = aux;
za magia?
 
Nie chce się zagłębiać, w to, lecz cała ta "funkcja: to wylęgarnia crashy, np:
PHP:
	while(aux->getParent())
	{
		prev = aux;
		aux = dynamic_cast<const Container*>(aux->getParent());
	}
zamienił bym:
PHP:
	while(aux->getParent())
	{
		prev = aux;ęc
		if(!aux = dynamic_cast<const Container*>(aux->getParent()))
                  break;
	}

To akurat nie ma najmniejszego sensu, gdyż rzutujemy na to samo i przypisanie na to samo.
PHP:
	if(dynamic_cast<const Container*>(prev))
		aux = aux;


Jeśli co kol wiek zaczynasz robić, to robisz najpierw algorytm na kartce. Wtedy dopiero masz wyobrażenie.
Tutaj za każdym razem musisz wykonać 2 rzeczy:
1) po dodaniu rzeczy zawsze wrócić do korzenia
2) policzyć "rzeczy", w każdym pojemniku, zaczynając od korzenia i mając na uwadze że każdy pojemnik


Sam algorytm jest nawet zaawansowany. I bez [Listy] nie wyobrażam sobie jak policzysz to.
Gdyż zawsze musisz szukać najpierw najdalszą gałąź na której zładuje się pojemnik, po policzeniu tego, cofać się o jedną gałąź i szukając pozostałych pojemników....

coś w tym stylu:
PHP:
void Foo() {
       Cointainer* korzeń = getRoot(this); // jeśli this to root, wtedy ok, a jak nie to niech znajdzie root
       int elementy = PoliczElement(korzen);
}

int PoliczElementy(Container* gałąź) {
       int ilośćElementów;
       for(/* Tutaj iteraot po kolei z pojemnika pobiera elemty*/) {
             if(isContainer(element)) { // jesli to pojemnik {
                 return PoliczElementy(*it);     
             }else
                ilośćElementów++;
       }
      return ilośćElementów;      
}


Wszystko to napisałem z głowy spontanicznie, więc ten algorytm pewnie nie jest poprawny i ma błędy.
Chodzi o to byś podchodził do problemy logicznie, próbując zrozumieć problem.

Tak samo nie możesz wymagać od Elfa, zaraz pod Ci gotowy kod, rzucił ci ogólny pomysł, wskazówki i to Ci powinno wystarczyć.
 
Wiesz, od strony logicznej to ja dawno miałem cały problem zanalizowany. Mój problem w tym wątku był natury czysto technicznej w nawet nie tyle C++, co samego kodu TFS i elementów takich jak Cylinder, Container i czy i kiedy można tego używać zamiennie. W każdym bądź razie, problem właśnie sam rozwiązałem tak, jak chciałem, więc temat do zamknięcia.

BTW, kod który zanalizowałeś i określiłeś jako "wylęgarnia crashy", to "kod" elfa :) On sam widocznie nie wie, co robi.
 
BTW, kod który zanalizowałeś i określiłeś jako "wylęgarnia crashy", to "kod" elfa :) On sam widocznie nie wie, co robi.

Wypraszam to sobie skurwielu, bo nie dość, że próbuje Ci pomóc- nie ważne, czy crashe, nie crashe, nie mam obowiązku pamiętać całego kodu ani nawet w ogóle Ci pomagać, a Ty mnie jeszcze obrażasz... Trochę kultury, ja pierdole. Nikt Ci nie karze dziękować, ale bez przesady.
 
nie ważne, czy crashe, nie crashe
Myśl przewodnia w pracy nad tfs rok 2007-2011 :D

Dobra dobra obrońcy looz, to taki żarcik.
Może właśnie czas zmienić fakt że polish board stał się sklejką wszystkich innych kategorii tego forum - w szczególności request i support. Paczeć na to się nie da
 
Myśl przewodnia w pracy nad tfs rok 2007-2011 :D

Dobra dobra obrońcy looz, to taki żarcik.
Może właśnie czas zmienić fakt że polish board stał się sklejką wszystkich innych kategorii tego forum - w szczególności request i support. Paczeć na to się nie da

Było zabronione - płacz, jest dozwolone - gorzej.
Polaczki biedaczki...
 
Back
Top