Contact:
*Link download / Code:
Nou Cum descarc de pe TeraBox?
Afișează detalii Ascunde detalii
- Este asemănător cu Mega.nz
- Instalați-vă clientul lor de Download de aici
- Faceți-vă un cont (vă puteți loga cu Facebook / Google / etc)
- Nou Dacă nu vreți să descărcați clientul de Download, folosiți acest site
- Gata! Acum puteți descărca resursele rapid & simplu.
De ce folosim TeraBox?
- Este gratuit
- Primești 1TB de spațiu gratuit la orice cont creat!
- Este ușor de folosit și varianta premium este foarte ieftină
- Fișierele nu sunt șterse niciodată
🔥 Hai pe Discord! - Chat activ și support direct
Te așteptăm și pe serverul de Discord - aici ne-am strâns toată comunitatea de Metin2 din România.
Alătură-te acum!
Suntem aproape:
Roboțelu'
Anunț
Hi! Thanks for the release, can I ask what it fixes?
Item duplicate fix
Contact:
Salutare, sunt la inceput de drum si inca invat, am la cineva pe server un shop offline cica asta ar fi dar partea de editare la shop dupa ce il creezi nu e total functionala , daca vreau sa adaug peste ce am deja in shop creat, nu apar itemele actuale in el si nici nu poti adauga altele adica ti le pune in fereastra dar daca o inchizi nu se pune in cel creat , idei ? sysser dupa ce adaug in el cu edit mode :
Code:
0201 13:48:26993 :: Traceback (most recent call last):
0201 13:48:26993 :: File "game.py", line 2120, in BINARY_ServerCommand_Run
0201 13:48:26993 :: File "stringCommander.py", line 63, in Run
0201 13:48:26993 :: File "stringCommander.py", line 31, in __call__
0201 13:48:26993 :: File "stringCommander.py", line 20, in __call__
0201 13:48:26993 :: File "game.py", line 2238, in ShopItem
0201 13:48:26994 :: IndexError
0201 13:48:26994 :: :
0201 13:48:26994 :: list index out of range
0201 13:48:26994 ::
0201 13:48:26994 :: Unknown Server Command shop_item 9043#16142#1#16#19999999#0#0|0|0#0,0|0,0|0,0|0,0|0,0|0,0|0,0 | shop_item
0201 14:01:32575 :: Traceback (most recent call last):
0201 14:01:32575 :: File "game.py", line 2120, in BINARY_ServerCommand_Run
0201 14:01:32575 :: File "stringCommander.py", line 63, in Run
0201 14:01:32575 :: File "stringCommander.py", line 31, in __call__
0201 14:01:32575 :: File "stringCommander.py", line 20, in __call__
0201 14:01:32575 :: File "game.py", line 2238, in ShopItem
0201 14:01:32575 :: IndexError
0201 14:01:32575 :: :
0201 14:01:32575 :: list index out of range
0201 14:01:32575 ::
0201 14:01:32575 :: Unknown Server Command shop_item 9043#16142#1#16#19999999#0#0|0|0#0,0|0,0|0,0|0,0|0,0|0,0|0,0 | shop_item
Ultima oară modificat 01 Feb 2026, 14:37 de către l3oogie, modificat 1 dată în total.
The server sends fewer or more # fields than the client expectsl3oogie scrie: ↑ Salutare, sunt la inceput de drum si inca invat, am la cineva pe server un shop offline cica asta ar fi dar partea de editare la shop dupa ce il creezi nu e total functionala , nu apar itemele actuale in el si nici nu poti adauga altele adica ti le pune in fereastra dar daca o inchizi nu se pune in cel creat , idei ? sysser dupa ce adaug in el cu edit mode :
Client usually does something like:
data = args.split("#")
vid = int(data[0])
vnum = int(data[1])
count = int(data[2])
pos = int(data[3])
price = long(data[4])
shopType = int(data[5])
sockets = data[6]
attrs = data[7]
0201 13:48:26994 :: Unknown Server Command shop_item 9043#16142#1#16#19999999#0#0|0|0#0,0|0,0|0,0|0,0|0,0|0,0|0,0 | shop_item
0201 14:01:32575 :: Traceback (most recent call last):
Contact:
Nermin scrie: ↑The server sends fewer or more # fields than the client expectsl3oogie scrie: ↑ Salutare, sunt la inceput de drum si inca invat, am la cineva pe server un shop offline cica asta ar fi dar partea de editare la shop dupa ce il creezi nu e total functionala , nu apar itemele actuale in el si nici nu poti adauga altele adica ti le pune in fereastra dar daca o inchizi nu se pune in cel creat , idei ? sysser dupa ce adaug in el cu edit mode :
Client usually does something like:
data = args.split("#")
vid = int(data[0])
vnum = int(data[1])
count = int(data[2])
pos = int(data[3])
price = long(data[4])
shopType = int(data[5])
sockets = data[6]
attrs = data[7]
0201 13:48:26994 :: Unknown Server Command shop_item 9043#16142#1#16#19999999#0#0|0|0#0,0|0,0|0,0|0,0|0,0|0,0|0,0 | shop_item
0201 14:01:32575 :: Traceback (most recent call last):
I understand now. The server side (game source) sends the shop items in a specific format, but the shop edit mode is using a different one, so it doesn’t read the list correctly.
I added another item just to see what happens, and yes — when I enter edit mode, the item appears and then instantly disappears because the data is not properly synchronized.
Ok, I understand this part now, but how should I rewrite it so that edit mode can correctly read the existing shop items from the server using the same format? I’m still a beginner and this already goes a bit beyond my current level.
Also, how should edit mode correctly add new items to an already existing shop (without overwriting the current ones), making sure the price, count, sockets, attributes, and all related data are saved and synchronized properly with the server?
Code:
class ShopEditWindow(ui.ScriptWindow):
def __init__(self):
ui.ScriptWindow.__init__(self)
self.items={}
self.Edit={}
self.pop=None
self.id=0
self.lastUpdate=0
self.priceInputBoard=None
self.__Load()
self.tooltipItem = uiToolTip.ItemToolTip()
self.tooltipItem.Hide()
def __del__(self):
ui.ScriptWindow.__del__(self)
self.Close()
def __Load_LoadScript(self, fileName):
try:
pyScriptLoader = ui.PythonScriptLoader()
pyScriptLoader.LoadScriptFile(self, fileName)
except:
import exception
exception.Abort("ShopEditWindow.__Load_LoadScript")
def __Load_BindObject(self):
try:
self.titleBar = self.GetChild("TitleBar")
self.titleName = self.GetChild("TitleName")
self.ItemSlot = self.GetChild("ItemSlot")
try:
for key in ["BuyButton","SellButton","MiddleTab1","MiddleTab2","MiddleTab2","SmallTab1","SmallTab2","SmallTab3"]:
self.GetChild(key).Hide()
except Exception:
pass
self.CloseButton = self.GetChild("CloseButton")
except:
import exception
exception.Abort("StoneDialog.__Load_BindObject")
self.CloseButton.SetText(uiScriptLocale.SHOP_EDIT_SHOP_CANCEL)
self.CloseButton.SetEvent(ui.__mem_func__(self.Close))
self.titleName.SetText(uiScriptLocale.SHOP_EDIT_SHOP_WINDOW)
self.titleBar.SetCloseEvent(ui.__mem_func__(self.Close))
self.ItemSlot.SAFE_SetButtonEvent("LEFT", "EMPTY", self.OnSelectEmptySlot)
self.ItemSlot.SAFE_SetButtonEvent("LEFT", "EXIST", self.OnSelectItemSlot)
self.ItemSlot.SAFE_SetButtonEvent("RIGHT", "EXIST", self.UnselectItemSlot)
self.ItemSlot.SetOverInItemEvent(ui.__mem_func__(self.OverInItem))
self.ItemSlot.SetOverOutItemEvent(ui.__mem_func__(self.OverOutItem))
self.Edit["Board"] = ui.BoardWithTitleBar()
self.Edit["Board"].SetSize(150, 100)
self.Edit["Board"].AddFlag("movable")
self.Edit["Board"].SetPosition(0,0)
self.Edit["Board"].SetTitleName(uiScriptLocale.SHOP_SELECT)
self.Edit["Board"].SetCloseEvent(self.CloseEdit)
self.Edit["Board"].Show()
self.Edit["ChangePrice"] = ui.Button()
self.Edit["ChangePrice"].SetParent(self.Edit["Board"])
self.Edit["ChangePrice"].SetPosition(30,35)
self.Edit["ChangePrice"].SetUpVisual('d:/ymir work/ui/public/Large_button_01.sub')
self.Edit["ChangePrice"].SetOverVisual('d:/ymir work/ui/public/Large_button_02.sub')
self.Edit["ChangePrice"].SetDownVisual('d:/ymir work/ui/public/Large_button_03.sub')
self.Edit["ChangePrice"].SetText(uiScriptLocale.SHOP_CHANGE_PRICE)
self.Edit["ChangePrice"].Show()
self.Edit["Remove"] = ui.Button()
self.Edit["Remove"].SetParent(self.Edit["Board"])
self.Edit["Remove"].SetPosition(30,65)
self.Edit["Remove"].SetUpVisual('d:/ymir work/ui/public/Large_button_01.sub')
self.Edit["Remove"].SetOverVisual('d:/ymir work/ui/public/Large_button_02.sub')
self.Edit["Remove"].SetDownVisual('d:/ymir work/ui/public/Large_button_03.sub')
self.Edit["Remove"].SetText(uiScriptLocale.SHOP_REMOVE_ITEM)
self.Edit["Remove"].Show()
def __Load(self):
self.__Load_LoadScript("UIScript/ShopDialog.py")
self.__Load_BindObject()
def CloseEdit(self):
self.Edit["Board"].Hide()
def Show(self,id):
if self.IsShow():
self.Close()
else:
ui.ScriptWindow.Show(self)
net.SendChatPacket("/update_shop_item edit_start|"+id)
net.SendChatPacket("/refresh_shop_items "+id)
self.id=id
self.Refresh()
def OnPressEscapeKey(self):
self.Close()
return TRUE
def __OnClosePopupDialog(self):
if self.pop != None:
if self.pop.IsShow():
self.pop.Hide()
self.pop = None
def __GetRealIndex(self, i):
return shop.SHOP_SLOT_COUNT + i
def Close(self):
if None != self.tooltipItem:
self.tooltipItem.HideToolTip()
self.CancelInputPrice()
self.__OnClosePopupDialog()
self.Edit["Board"].Hide()
self.Hide()
return TRUE
def Clear(self):
self.items={}
self.CancelInputPrice()
self.__OnClosePopupDialog()
self.Edit["Board"].Hide()
self.Refresh()
def GetItemCount(self,slot):
try:
return int(self.items[int(slot)]["count"])
except KeyError:
return 0
def GetItemID(self,slot):
try:
return int(self.items[int(slot)]["vnum"])
except KeyError:
return 0
def AddItem(self,slot,data):
self.items[int(slot)]=data
self.Refresh()
def Refresh(self):
self.CancelInputPrice()
self.__OnClosePopupDialog()
self.Edit["Board"].Hide()
setItemID=self.ItemSlot.SetItemSlot
for i in xrange(shop.SHOP_SLOT_COUNT):
vnum=self.GetItemID(i)
itemCount = self.GetItemCount(i)
setItemID(i, vnum, itemCount)
wndMgr.RefreshSlot(self.ItemSlot.GetWindowHandle())
self.ItemSlot.RefreshSlot()
def __ShowToolTip(self, slot):
if self.tooltipItem:
self.tooltipItem.ClearToolTip()
if int(slot) in self.items.keys():
it=self.items[int(slot)]
if it.get("sourceSlot",-1)!=-1:
self.tooltipItem.SetEditPrivateShopItem(int(it["sourceWindow"]),int(it["sourceSlot"]),it["price"])
else:
self.tooltipItem.AppendSellingPrice(it["price"])
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
self.tooltipItem.AppendSellingCheque2(it["cheque"])
self.tooltipItem.AddItemData(int(it["vnum"]),it["sockets"],it["attrs"])
else:
self.tooltipItem.HideToolTip()
def OverInItem(self, slotIndex):
#slotIndex = self.__GetRealIndex(slotIndex)
self.ItemSlot.SetUsableItem(FALSE)
self.__ShowToolTip(slotIndex)
def OverOutItem(self):
self.ItemSlot.SetUsableItem(FALSE)
if self.tooltipItem:
self.tooltipItem.HideToolTip()
def OnSelectEmptySlot(self, selectedSlotPos):
isAttached = mouseModule.mouseController.isAttached()
if isAttached:
attachedSlotType = mouseModule.mouseController.GetAttachedType()
attachedSlotPos = mouseModule.mouseController.GetAttachedSlotNumber()
mouseModule.mouseController.DeattachObject()
if player.SLOT_TYPE_INVENTORY != attachedSlotType and player.SLOT_TYPE_DRAGON_SOUL_INVENTORY != attachedSlotType:
return
attachedInvenType = player.SlotTypeToInvenType(attachedSlotType)
count = player.GetItemCount(attachedInvenType, attachedSlotPos)
itemVNum = player.GetItemIndex(attachedInvenType, attachedSlotPos)
item.SelectItem(itemVNum)
if item.IsAntiFlag(item.ANTIFLAG_GIVE) or item.IsAntiFlag(item.ANTIFLAG_MYSHOP):
chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.PRIVATE_SHOP_CANNOT_SELL_ITEM)
return
priceInputBoard = uiCommon.MoneyInputDialog()
priceInputBoard.SetTitle(localeInfo.PRIVATE_SHOP_INPUT_PRICE_DIALOG_TITLE)
priceInputBoard.SetAcceptEvent(ui.__mem_func__(self.AcceptInputPrice))
priceInputBoard.SetCancelEvent(ui.__mem_func__(self.CancelInputPrice))
priceInputBoard.SetMaxLength(16)
priceInputBoard.Open()
#self.ItemSlot.ActivateSlot(int(selectedSlotPos))
self.priceInputBoard = priceInputBoard
self.priceInputBoard.itemVNum = itemVNum
self.priceInputBoard.sourceWindowType = attachedInvenType
self.priceInputBoard.sourceSlotPos = attachedSlotPos
self.priceInputBoard.targetSlotPos = selectedSlotPos
def UnselectItemSlot(self,selectedSlotPos):
self.Edit["Board"].Hide()
#self.ItemSlot.DeactivateSlot(int(selectedSlotPos))
self.CancelInputPrice()
self.__OnClosePopupDialog()
def OnSelectItemSlot(self, selectedSlotPos):
isAttached = mouseModule.mouseController.isAttached()
#selectedSlotPos = self.__GetRealIndex(selectedSlotPos)
if isAttached:
snd.PlaySound("sound/ui/loginfail.wav")
#self.ItemSlot.DeactivateSlot(int(selectedSlotPos))
mouseModule.mouseController.DeattachObject()
self.Edit["Board"].Hide()
else:
if not int(selectedSlotPos) in self.items.keys():
self.Edit["Board"].Hide()
return
snd.PlaySound("sound/ui/drop.wav")
#self.ItemSlot.ActivateSlot(selectedSlotPos)
self.EditItem(selectedSlotPos)
def AcceptInputPrice(self):
if not self.priceInputBoard:
return True
text = self.priceInputBoard.GetText()
if not text:
return True
if not text.isdigit():
return True
if int(text) <= 0:
return True
attachedInvenType = self.priceInputBoard.sourceWindowType
sourceSlotPos = self.priceInputBoard.sourceSlotPos
targetSlotPos = self.priceInputBoard.targetSlotPos
price = int(self.priceInputBoard.GetText())
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
cheque = int(self.priceInputBoard.GetTextCheque())
count = player.GetItemCount(attachedInvenType, sourceSlotPos)
vnum = player.GetItemIndex(attachedInvenType, sourceSlotPos)
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
self.items[int(targetSlotPos)]={
"vnum":int(vnum),
"count":int(count),
"price":int(price),
"cheque":int(cheque),
"sourceSlot":sourceSlotPos,
"sourceWindow":attachedInvenType
}
else:
self.items[int(targetSlotPos)]={
"vnum":int(vnum),
"count":int(count),
"price":int(price),
"sourceSlot":sourceSlotPos,
"sourceWindow":attachedInvenType
}
snd.PlaySound("sound/ui/pick.wav")
#self.ItemSlot.DeactivateSlot(targetSlotPos)
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
net.SendChatPacket("/update_shop_item add|%d|%d|%d|%d|%s|%s"%(int(self.id),int(targetSlotPos),int(sourceSlotPos),int(attachedInvenType),str(price), str(cheque)))
else:
net.SendChatPacket("/update_shop_item add|%d|%d|%d|%d|%s"%(int(self.id),int(targetSlotPos),int(sourceSlotPos),int(attachedInvenType),str(price)))
self.Refresh()
#####
self.priceInputBoard = None
return True
def CancelInputPrice(self):
self.priceInputBoard = None
return True
def EditItem(self,slot):
self.Edit["ChangePrice"].SetEvent(ui.__mem_func__(self.EditPrice),int(slot))
self.Edit["Remove"].SetEvent(ui.__mem_func__(self.RemoveItem),int(slot))
(w,h)=(170,328)
(x,y)=self.GetLocalPosition()
self.Edit["Board"].SetPosition((x-w),(y+(h/2)))
self.Edit["Board"].Show()
def EditPrice(self,slot):
self.priceInputBoard = uiCommon.MoneyInputDialog()
self.priceInputBoard.SetTitle(localeInfo.PRIVATE_SHOP_INPUT_PRICE_DIALOG_TITLE)
self.priceInputBoard.SetAcceptEvent(ui.__mem_func__(self.AcceptEditPrice))
self.priceInputBoard.SetCancelEvent(ui.__mem_func__(self.CancelInputPrice))
self.priceInputBoard.SetMaxLength(16)
self.priceInputBoard.Open()
self.priceInputBoard.targetSlotPos = int(slot)
def RemoveItem(self,slot):
self.pop = uiCommon.QuestionDialog()
self.pop.SetText(uiScriptLocale.SHOP_REMOVE_ITEM_QUEST)
self.pop.SetAcceptEvent(lambda arg1=str(slot): self.AcceptRemoveItem(arg1))
self.pop.SetCancelEvent(ui.__mem_func__(self.__OnClosePopupDialog))
self.pop.Open()
def AcceptRemoveItem(self,slot):
if int(slot) in self.items.keys():
snd.PlaySound("sound/ui/drop.wav")
net.SendChatPacket("/update_shop_item remove|"+str(self.id)+"|"+str(self.items[int(slot)]["id"]))
#self.ItemSlot.DeactivateSlot(int(slot))
del self.items[int(slot)]
self.Refresh()
self.__OnClosePopupDialog()
def AcceptEditPrice(self):
if not self.priceInputBoard:
return True
text = self.priceInputBoard.GetText()
if not text:
return True
if not text.isdigit():
return True
if int(text) <= 0:
return True
targetSlotPos = self.priceInputBoard.targetSlotPos
price = int(self.priceInputBoard.GetText())
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
cheque = int(self.priceInputBoard.GetTextCheque())
#self.ItemSlot.DeactivateSlot(int(targetSlotPos))
self.items[int(targetSlotPos)]["price"]=price
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
self.items[int(targetSlotPos)]["cheque"]=cheque
snd.PlaySound("sound/ui/drop.wav")
if app.ENABLE_OFFLINE_SHOP_USE_CHEQUE:
net.SendChatPacket("/update_shop_item price|"+str(self.id)+"|"+str(self.items[int(targetSlotPos)]["id"])+"|"+str(price)+"|"+str(cheque))
else:
net.SendChatPacket("/update_shop_item price|"+str(self.id)+"|"+str(self.items[int(targetSlotPos)]["id"])+"|"+str(price))
self.Refresh()
self.priceInputBoard = None
return True
def OnUpdate(self):
if self.IsShow() and self.lastUpdate < app.GetGlobalTime():
self.lastUpdate=app.GetGlobalTime()+1000
if int(self.id)>0:
net.SendChatPacket("/update_shop_item edit_tick|"+self.id)
📢 Resurse Metin2 Premium!
Zeci de resurse Metin2 Premium - exclusive și 100% funcționale începând cu 15.99€!.
Vezi resursele Cumpără premium
Premium
Anunț
Creează-ți un cont sau autentifică-te pentru a participa la discuție
Trebuie să fii membru pentru a răspunde
Creează-ți un cont
Membrii pot crea subiecte noi și pot descărca resurse Metin2 Gratuit!
Te poți înregistra sau conecta rapid utilizând contul tău de Discord, Github sau Google.
Autentifică-te
-
Subiecte similare
-
2Răspunsuri630Vizualizăride Angelic
-
2Răspunsuri440Vizualizăride YTmaster
-
3Răspunsuri904Vizualizăride lottryy
-
9Răspunsuri3037Vizualizăride diehard2998
-
2Răspunsuri1047Vizualizăride [HF]White
-
Informații
Utilizatori ce navighează pe acest forum: mesomloco și 2 vizitatori
Discord ID copiat:

la acest mesaj și conținutul se va afișa automat.







