reiki/reiki.py

902 lines
46 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding: utf-8
# 灵气系统 by DreamCityToger
import random
import pyspigot as ps
from org.bukkit import Material, Sound, Particle
from org.bukkit.util import Vector
from org.bukkit.entity import Player
from org.bukkit.potion import PotionEffect, PotionEffectType
from org.bukkit.Bukkit import getServer
from org.bukkit.inventory import ItemStack, EquipmentSlot
from org.bukkit.enchantments import Enchantment
from org.bukkit.event.player import PlayerInteractEvent
from org.bukkit.event.inventory import InventoryClickEvent
from org.bukkit.event.inventory import InventoryDragEvent
from org.bukkit.event.inventory import InventoryCloseEvent
from util2.develop.gui.builder import initializeItemStack
from util2.develop.gui.builder import getGUIValue
from util2.develop.gui.manager import GUIManager
from util2.develop.gui.manager import GUIController
from util2.develop.gui.builder import isGUI
from util2.develop.gui.bugfixer import closeGuiForAll
from util2.develop.gui.bugfixer import cancelShiftClickFromPlayerInventory
from util2.develop.gui.bugfixer import denyAllInventoryDrag
from util2.plugins.head import PlayerHeadsAPI
WORLD_NAME = u"Old_World"
MIN_TODAY_PRO = 0.0 #天时最小值
MAX_TODAY_PRO = 10.0 #天时最大值
MIN_REIKI_PRO = 0.0 #地利最小值
MAX_REIKI_PRO = 10.0 #地利最大值
guiManager = GUIManager() #菜单管理
playerHeadsAPI = PlayerHeadsAPI() # 初始化Player Heads
playerPage = {} #玩家页数
class WorldManager: #世界管理
def __init__(self):
self.world = getServer().getWorld(WORLD_NAME)
def getWorld(self): #获取世界对象
return self.world
worldManager = WorldManager()
class ItemsManager:
def __init__(self):
self.itemsData = ps.config.loadConfig("reiki/items.yml")
self.itemsData.save()
self.initialElementItems()
def initialElementItems(self):
self.grassItems = []
self.fireItems = []
self.waterItems = []
self.earthItems = []
self.thunderItems = []
self.iceItems = []
self.windItems = []
items = self.itemsData.getKeys(False)
for itemId in items:
element = self.itemsData.getString("{}.element".format(itemId), None)
if element is None:
continue
if element == u"GRASS":
self.grassItems.append(itemId)
elif element == u"FIRE":
self.fireItems.append(itemId)
elif element == u"WATER":
self.waterItems.append(itemId)
elif element == u"EARTH":
self.earthItems.append(itemId)
elif element == u"THUNDER":
self.thunderItems.append(itemId)
elif element == u"ICE":
self.iceItems.append(itemId)
elif element == u"WIND":
self.windItems.append(itemId)
def getAllItems(self): #获取所有道具
items = self.itemsData.getKeys(False)
return items
def getItemstack(self, itemId=0):
if str(itemId) not in self.itemsData.getKeys(False): #若不存在该Id道具
return None
material = self.itemsData.getString("{}.material".format(itemId), u"DANDELION")
itemstack = ItemStack(Material.valueOf(material), 1)
itemMeta = itemstack.getItemMeta()
enchantmentsSection = self.itemsData.get("{}.enchantments".format(itemId))
if enchantmentsSection is not None:
enchantments = enchantmentsSection.getKeys(False)
for enchantment in enchantments:
enchant = Enchantment.getByName(enchantment)
if enchant is not None:
level = enchantmentsSection.getInt(enchantment, 1)
itemMeta.addEnchant(enchant, level, True)
itemstack.setItemMeta(itemMeta)
display = self.itemsData.getString("{}.display".format(itemId), u"§f未命名道具")
lores = self.itemsData.get("{}.lores".format(itemId), [])
key = self.itemsData.getString("{}.key".format(itemId), None)
if key is None:
key = u"ITEM" #默认关键字
item = initializeItemStack(itemstack, display, *lores, data=u"reiki:{}".format(key))
return item
def getItemDisplay(self, itemId=0):
if str(itemId) not in self.itemsData.getKeys(False):
return None
display = self.itemsData.getString("{}.display".format(itemId), u"§f未命名道具")
return display
itemManager = ItemsManager()
class BlockManager:
def __init__(self):
self.blockData = ps.config.loadConfig("reiki/block.yml")
self.blockData.save()
self.todayPro = 5.0 #每日运势
self.randomTodayPro()
#存储不同灵气台的内容
self.taskIds = {}
self.offY = {}
self.keys = {}
self.mutation = {}
self.working = {}
self.element = {}
self.itemId = {}
self.players= {}
#灵气台管理--------------------------------
def getLocTable(self, loc): #获取对应位置的灵气台
x = loc.getBlockX()
y = loc.getBlockY()
z = loc.getBlockZ()
for blockId in self.blockData.getKeys(False):
if self.blockData.getInt("{}.x".format(blockId)) == x:
if self.blockData.getInt("{}.y".format(blockId)) == y:
if self.blockData.getInt("{}.z".format(blockId)) == z:
return blockId
return None
def createReikiTable(self, loc): #创造一个灵气台
if self.getLocTable(loc): #若已经存在
return False
blockId = str(self.getNewTableID())
self.blockData.set("{}.x".format(blockId), loc.getBlockX())
self.blockData.set("{}.y".format(blockId), loc.getBlockY())
self.blockData.set("{}.z".format(blockId), loc.getBlockZ())
self.blockData.set("{}.world".format(blockId), loc.getWorld().getName())
self.blockData.set("{}.name".format(blockId), u"普通灵气台")
self.blockData.set("{}.grass".format(blockId), 1)
self.blockData.set("{}.fire".format(blockId), 1)
self.blockData.set("{}.water".format(blockId), 1)
self.blockData.set("{}.earth".format(blockId), 1)
self.blockData.set("{}.thunder".format(blockId), 1)
self.blockData.set("{}.ice".format(blockId), 1)
self.blockData.set("{}.wind".format(blockId), 1)
self.blockData.set("{}.timesOfUse".format(blockId), 0) #使用过的次数
self.blockData.set("{}.timesOfMutation".format(blockId), 0) #突变召唤次数
self.blockData.save()
return blockId
def delReikiTable(self, blockId): #删除对应Id的灵气台
if str(blockId) not in self.blockData.getKeys(False):
return False
self.blockData.set(blockId, None)
self.blockData.save()
return True
def getTableLoc(self, blockId): #获取灵气台的位置
if str(blockId) not in self.blockData.getKeys(False):
return None
x = self.blockData.getInt("{}.x".format(blockId))
y = self.blockData.getInt("{}.y".format(blockId))
z = self.blockData.getInt("{}.z".format(blockId))
world = worldManager.getWorld()
return world.getBlockAt(x, y, z).getLocation()
def getNewTableID(self): #获取一个新的灵气台ID
currentID = 1
keys = self.blockData.getKeys(False)
while True:
if self.blockData.get(str(currentID)) is None:
return currentID
if str(currentID) not in keys:
return currentID
else:
currentID += 1
def getTableElement(self, blockId, element=u"GRASS"): #获取灵气台的元素
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return None
if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在
return None
value = self.blockData.getInt("{}.{}".format(blockId, element.lower()), 0) #获取
return value
def getTableName(self, blockId): #获取灵气台的名称
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return None
name = self.blockData.getString("{}.name".format(blockId), u"§f普通灵气台") #获取
return name
def setTableElement(self, blockId, element=u"GRASS", value=11):
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return False
if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在
return False
self.blockData.set("{}.{}".format(blockId, element.lower()), value) #设置
self.blockData.save() #保存
return True
def setTableName(self, blockId, name): #设置灵气台的名称
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return False
self.blockData.set("{}.name".format(blockId), name) #设置
self.blockData.save() #保存
return True
def addTableTimesOfUse(self, blockId): #增加灵气台使用次数
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return False
timesOfUse = self.blockData.getInt("{}.timesOfUse".format(blockId), 0) #获取
self.blockData.set("{}.timesOfUse".format(blockId), timesOfUse + 1) #设置
self.blockData.save() #保存
return True
def addTableTimesOfMutation(self, blockId): #增加灵气台使用次数
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return False
timesOfMutation = self.blockData.getInt("{}.timesOfMutation".format(blockId), 0) #获取
self.blockData.set("{}.timesOfMutation".format(blockId), timesOfMutation + 1) #设置
self.blockData.save() #保存
return True
def addTableTimesOfElement(self, blockId, element=u"grass"):
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return False
if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在
return False
timesOfElement = self.blockData.getInt("{}.timesOf{}".format(blockId, element.lower()), 0) #获取
self.blockData.set("{}.timesOf{}".format(blockId, element.lower()), timesOfElement + 1) #设置
self.blockData.save() #保存
return True
#灵气召唤--------------------------------
def reikiCall(self, player, blockId, key=u"DANDELION", mutation=False): #灵气召唤
if str(blockId) not in self.blockData.getKeys(False): #若不存在
return False
if blockId not in self.working:
self.working[blockId] = False #设置为未工作
if self.working[blockId]: #若正在工作
return False
#效果
loc = self.getTableLoc(blockId)
world = loc.getWorld()
world.playSound(loc, Sound.BLOCK_BELL_RESONATE, 1.0, 1.0) #播放声音
world.spawnParticle(Particle.ENCHANT, loc.add(Vector(0.5,1.5,0.5)), 300, 0.3, 0.4, 0.3, 0)
element, itemId = self.selectElementAndItem(blockId) #抽取元素和物品
self.working[blockId] = True #设置正在工作
self.offY[blockId] = 2.0 #重置Y偏移
self.keys[blockId] = key #设置关键字
self.mutation[blockId] = mutation #设置是否为突变
self.element[blockId] = element #设置元素
self.itemId[blockId] = itemId #设置物品
self.players[blockId] = player #设置玩家
playerManager = PlayerManager(player)
playerManager.setGetting(True)
self.taskIds[blockId] = ps.scheduler.scheduleRepeatingTask(lambda s=self, b=blockId, m=mutation, : s.spawnParticles(b, m), 0, 1)
return True
def reikiCallEnd(self, blockId):
key = self.keys[blockId] #获取关键字
mutation = self.mutation[blockId] #获取是否为突变
loc = self.getTableLoc(blockId)
world = loc.getWorld()
blockManager.addTableTimesOfUse(blockId) #增加使用次数
player = self.players[blockId] #获取玩家
playerManager = PlayerManager(player) #获取玩家管理器
playerManager.addTimesOfUse()
if key == u"DANDELION": #如果是蒲公英
if mutation: #如果是突变
world.spawnParticle(Particle.REVERSE_PORTAL, loc.add(Vector(0.5,0.9,0.5)), 100, 0.25, 0.06, 0.25, 0) #播放粒子
world.playSound(loc, Sound.ENTITY_PLAYER_LEVELUP, 0.5, 2.0) #播放声音
playerManager.upgradeLuck()
playerManager.addTimesOfElement(self.element[blockId])
playerManager.addTimesOfMutation()
blockManager.addTableTimesOfMutation(blockId) #增加突变次数
blockManager.addTableTimesOfElement(blockId, self.element[blockId]) #增加元素次数
message = u"§d[灵气] §e{} §a在{}§a成功召唤出 {} §a".format(player.getName(), self.getTableName(blockId), itemManager.getItemDisplay(self.itemId[blockId])) #消息
getServer().broadcastMessage(message)
self.dropItem(blockId, self.itemId[blockId]) #掉落
else: #如果不是
self.dropItem(blockId, 1) #掉落
playerManager.setGetting(False) #结束获取
def spawnParticles(self, blockId, mutation=False):
if str(blockId) not in self.blockData.getKeys(False):
return False
loc = self.getTableLoc(blockId)
world = loc.getWorld()
if mutation:
element = self.element[blockId]
world.playSound(loc, Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1.0, 1.0) #播放声音
if element == u"grass":
world.spawnParticle(Particle.SPORE_BLOSSOM_AIR, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0)
elif element == u"fire":
world.spawnParticle(Particle.FLAME, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0.05)
elif element == u"water":
world.spawnParticle(Particle.DOLPHIN, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 10, 0.05, 0, 0.05, 0)
elif element == u"earth":
world.spawnParticle(Particle.WAX_ON, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0.2, 0, 0.2, 0)
elif element == u"thunder":
world.spawnParticle(Particle.FLASH, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0)
elif element == u"ice":
world.spawnParticle(Particle.SNOWFLAKE, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0)
elif element == u"wind":
world.spawnParticle(Particle.CLOUD, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0.02)
else:
world.spawnParticle(Particle.DRAGON_BREATH, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0.02, 0, 0.02, 0)
else:
world.spawnParticle(Particle.HAPPY_VILLAGER, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0.1, 0, 0.1, 0)
self.offY[blockId] -= 0.05 #增加Y偏移
if self.offY[blockId] <= 0: #若Y偏移小于等于0
self.stopTask(blockId) #停止任务
self.reikiCallEnd(blockId) #灵气台反馈
self.working[blockId] = False #设置为未工作
def selectElementAndItem(self, blockId):
if str(blockId) not in self.blockData.getKeys(False):
return None, None
# 加权抽取元素
elements = ['grass', 'fire', 'water', 'earth', 'thunder', 'ice', 'wind']
elementWeights = {element: self.blockData.getInt(u"{}.{}".format(blockId, element)) for element in elements}
selectedElement = self.weightedRandomSelection(elementWeights)
# 根据元素获取对应物品列表
if selectedElement == 'grass':
itemList = itemManager.grassItems
elif selectedElement == 'fire':
itemList = itemManager.fireItems
elif selectedElement == 'water':
itemList = itemManager.waterItems
elif selectedElement == 'earth':
itemList = itemManager.earthItems
elif selectedElement == 'thunder':
itemList = itemManager.thunderItems
elif selectedElement == 'ice':
itemList = itemManager.iceItems
elif selectedElement == 'wind':
itemList = itemManager.windItems
else:
return None, None
# 加权抽取物品
itemWeights = {}
for itemId in itemList:
weight = itemManager.itemsData.getInt(u"{}.weight".format(itemId), 1)
itemWeights[str(itemId)] = weight
selectedItem = self.weightedRandomSelection(itemWeights)
return selectedElement, selectedItem
def weightedRandomSelection(self, weights):
totalWeight = sum(weights.values())
randomNum = random.uniform(0, totalWeight)
cumulativeWeight = 0
for item, weight in weights.items():
cumulativeWeight += weight
if randomNum <= cumulativeWeight:
return item
def stopTask(self, blockId):
if blockId in self.taskIds:
taskId = self.taskIds[blockId]
if taskId is not None:
ps.scheduler.stopTask(taskId)
self.taskIds[blockId] = None
def dropItem(self, blockId, itemId=1):
if str(blockId) not in self.blockData.getKeys(False):
return False
item = itemManager.getItemstack(itemId)
if item is None:
return False
loc = self.getTableLoc(blockId)
world = loc.getWorld()
droppedItem = world.dropItem(loc.add(Vector(0.5,1,0.5)), item)
droppedItem.setVelocity(Vector(0, 0, 0))
world.playSound(loc, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0, 1.0)
return True
#运势管理
def setTodayPro(self, pro=5.0): #设置当日概率
self.todayPro = pro
def randomTodayPro(self):
rand = random.uniform(MIN_TODAY_PRO,MAX_TODAY_PRO)
self.setTodayPro(rand)
def getTodayPro(self): #获取今日运势概率
return self.todayPro
def getReikiTablePro(self, blockId): #获取灵气台概率
if str(blockId) not in self.blockData.getKeys(False): #若不存在该灵气台
return None
timesOfUse = self.blockData.getInt("{}.timesOfUse".format(blockId), 0) #获取
timesOfMutation = self.blockData.getInt("{}.timesOfMutation".format(blockId), 0) #获取
pro = (float(timesOfUse - timesOfMutation + 50) / float(timesOfUse + 100)) * 10 #计算
return pro
def getPlayerPro(self, player): #获取玩家概率
playerName = player.getName()
playerData = ps.config.loadConfig("reiki/player.yml")
timesOfUse = playerData.getInt("{}.timesOfUse".format(playerName), 0) #获取
timesOfMutation = playerData.getInt("{}.timesOfMutation".format(playerName), 0) #获取
pro = (float(timesOfUse - timesOfMutation + 50) / float(timesOfUse + 100)) * 10 #计算
luck = player.getPotionEffect(PotionEffectType.LUCK)
unluck = player.getPotionEffect(PotionEffectType.UNLUCK)
if luck is not None:
luckLevel = luck.getAmplifier() + 1
luckBonus = min(luckLevel * 2, 14)
pro += luckBonus
if unluck is not None:
unluckLevel = unluck.getAmplifier() + 1
unluckPenalty = min(unluckLevel * 2, 14)
pro -= unluckPenalty
return pro
def getPro(self, player, blockId): #获取概率
pro = self.getPlayerPro(player) + self.getReikiTablePro(blockId) + self.getTodayPro()
pro = max(0.0, min(pro, 100.0)) #限制概率范围
return pro
blockManager = BlockManager()
class PlayerManager:
def __init__(self, player):
self.player = player
def getTargetFrameLocation(self):
targetBlock = self.player.getTargetBlockExact(5)
if targetBlock is not None:
if targetBlock.getType() == Material.END_PORTAL_FRAME:
loc = targetBlock.getLocation()
if loc.getWorld().getName() == WORLD_NAME:
return loc
return None
def drawPro(self, pro=5.0): #按概率判断成功
pro = max(0.0, min(pro, 100.0))
randomValue = random.uniform(0.0, 100.0)
return randomValue <= pro
def reikiCall(self, blockId, key=u"DANDELION"): #灵气召唤
pro = blockManager.getPro(self.player, blockId) #获取概率
mutation = self.drawPro(pro) #抽奖
if mutation:
result = blockManager.reikiCall(self.player, blockId, key, mutation=True)
else:
result = blockManager.reikiCall(self.player, blockId, key, mutation=False)
if result:
return True
else:
return False
def upgradeLuck(self):
luck = self.player.getPotionEffect(PotionEffectType.LUCK)
if luck is not None:
luckLevel = luck.getAmplifier() + 1 # 效果等级从 0 开始,所以加 1
luckLevel = min(luckLevel, 6) # 最大等级为 7
self.player.addPotionEffect(PotionEffect(PotionEffectType.LUCK, 72000, luckLevel, True, False))
else:
self.player.addPotionEffect(PotionEffect(PotionEffectType.LUCK, 72000, 0, True, False))
def addTimesOfUse(self):
playerData = ps.config.loadConfig("reiki/player.yml")
timesOfUse = playerData.getInt("{}.timesOfUse".format(self.player.getName()), 0)
playerData.set("{}.timesOfUse".format(self.player.getName()), timesOfUse + 1)
playerData.save()
def addTimesOfMutation(self):
playerData = ps.config.loadConfig("reiki/player.yml")
timesOfMutation = playerData.getInt("{}.timesOfMutation".format(self.player.getName()), 0)
playerData.set("{}.timesOfMutation".format(self.player.getName()), timesOfMutation + 1)
playerData.save()
def addTimesOfElement(self, element=u"grass"):
if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在
return False
playerData = ps.config.loadConfig("reiki/player.yml")
timesOfElement = playerData.getInt("{}.timesOf{}".format(self.player.getName(), element.lower()), 0)
playerData.set("{}.timesOf{}".format(self.player.getName(), element.lower()), timesOfElement + 1)
playerData.save()
def setGetting(self, value=True):
playerData = ps.config.loadConfig("reiki/player.yml")
playerData.set("{}.getting".format(self.player.getName()), value)
playerData.save()
class MenuReikiInfo(GUIController):# 单人房间菜单
def __init__(self, player, blockId):
super(MenuReikiInfo, self).__init__(player)
self.blockId = blockId
self.tableName = blockManager.getTableName(blockId)
self.setInfo("reiki.info", u"§0[灵气]{} 信息一览".format(self.tableName))
self.setGUIManager(guiManager)
def render(self):
player = self.getPlayer()
playerName = player.getName()
pro = blockManager.getPro(player, self.blockId)
todayPro = blockManager.getTodayPro()
playerPro = blockManager.getPlayerPro(player)
reikiPro = blockManager.getReikiTablePro(self.blockId)
playerData = ps.config.loadConfig("reiki/player.yml")
playerTimesOfUse = playerData.getInt("{}.timesOfUse".format(playerName), 0)
playerTimesOfMutation = playerData.getInt("{}.timesOfMutation".format(playerName), 0)
playerMutationPro = (float(playerTimesOfMutation) / float(playerTimesOfUse)) * 100 if playerTimesOfUse > 0 else 0
blockTimesOfUse = blockManager.blockData.getInt("{}.timesOfUse".format(self.blockId), 0)
blockTimesOfMutation = blockManager.blockData.getInt("{}.timesOfMutation".format(self.blockId), 0)
blockMutationPro = (float(blockTimesOfMutation) / float(blockTimesOfUse)) * 100 if blockTimesOfUse > 0 else 0
self.set(2, playerHeadsAPI.getPlayerHead(playerName), u"§b§l✟ §e§l召唤历史 §b§l✟",
u"§e个人总运势 §f{:.2f}% §7[{}/{}]".format(playerMutationPro, playerTimesOfMutation, playerTimesOfUse),
u"§e本台总运势 §f{:.2f}% §7[{}/{}]".format(blockMutationPro, blockTimesOfMutation, blockTimesOfUse))
self.set(4, Material.END_PORTAL_FRAME, u"§5§l☯ §d§l本台运势 §5§l☯",
u"§e当前运势 §f{:.2f}%".format(pro),
u"§f",
u"§e天时 §f{:.2f} §7[0, 10]".format(todayPro),
u"§e地利 §f{:.2f} §7[0, 10)".format(reikiPro),
u"§e人和 §f{:.2f} §7[0, 24)".format(playerPro),
u"§f",
u"§6>> §e点击查看所有灵气台信息 §6<<")
self.set(6, Material.DANDELION, u"§7§l✿ §a§l召唤物图鉴 §7§l✿",
u"§f",
u"§6>> §e点击查阅图鉴 §6<<")
self.set(19, Material.WHEAT_SEEDS, u"§7§l✿ §a§l草元素召唤次数 §7§l✿",
u"§a本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfgrass".format(self.blockId), 0), blockTimesOfMutation),
u"§a个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOfgrass".format(playerName), 0), playerTimesOfMutation))
self.set(20, Material.BLAZE_POWDER, u"§7§l✿ §c§l火元素召唤次数 §7§l✿",
u"§c本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOffire".format(self.blockId), 0),blockTimesOfMutation),
u"§c个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOffire".format(playerName), 0), playerTimesOfMutation))
self.set(21, Material.HEART_OF_THE_SEA, u"§7§l✿ §3§l水元素召唤次数 §7§l✿",
u"§3本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfwater".format(self.blockId), 0),blockTimesOfMutation),
u"§3个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOfwater".format(playerName), 0), playerTimesOfMutation))
self.set(22, Material.COCOA_BEANS, u"§7§l✿ §6§l地元素召唤次数 §7§l✿",
u"§6本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfearth".format(self.blockId), 0),blockTimesOfMutation),
u"§6个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOfearth".format(playerName), 0), playerTimesOfMutation))
self.set(23, Material.NETHER_STAR, u"§7§l✿ §e§l雷元素召唤次数 §7§l✿",
u"§e本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfthunder".format(self.blockId), 0),blockTimesOfMutation),
u"§e个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOfthunder".format(playerName), 0), playerTimesOfMutation))
self.set(24, Material.SNOWBALL, u"§7§l✿ §b§l冰元素召唤次数 §7§l✿",
u"§b本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfice".format(self.blockId), 0),blockTimesOfMutation),
u"§b个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOfice".format(playerName), 0), playerTimesOfMutation))
self.set(25, Material.FEATHER, u"§7§l✿ §f§l风元素召唤次数 §7§l✿",
u"§f本台次数 §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfwind".format(self.blockId), 0),blockTimesOfMutation),
u"§f个人次数 §f{}§7/{}".format(playerData.getInt("{}.timesOfwind".format(playerName), 0), playerTimesOfMutation))
self.spawnSeparators(0, 18, vertical=True)
self.spawnSeparators(8, 26, vertical=True)
def onClick(self, e):
e.setCancelled(True)
clickInt = e.getSlot()
player = self.getPlayer()
if clickInt == 4:
MenuReikiTable(player).openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 6:
MenuItems(player).openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
class MenuItems(GUIController):# 物品图鉴
def __init__(self, player, page=1, element=u"none"):
super(MenuItems, self).__init__(player)
self.page = page
self.element = element
self.setInfo("reiki.items", u"§0[灵气]召唤物图鉴 第{}".format(self.page))
self.setGUIManager(guiManager)
def render(self):
player = self.getPlayer()
playerName = player.getName()
if self.element.lower() == u"none":
items = list(itemManager.getAllItems())
elif self.element.lower() == u"grass":
items = list(itemManager.grassItems)
elif self.element.lower() == u"fire":
items = list(itemManager.fireItems)
elif self.element.lower() == u"water":
items = list(itemManager.waterItems)
elif self.element.lower() == u"earth":
items = list(itemManager.earthItems)
elif self.element.lower() == u"thunder":
items = list(itemManager.thunderItems)
elif self.element.lower() == u"ice":
items = list(itemManager.iceItems)
elif self.element.lower() == u"wind":
items = list(itemManager.windItems)
else:
items = list(itemManager.getAllItems())
itemsPerPage = 45 # 每页显示 45 个物品,最后一行用于控制
self.totalPages = (len(items) + itemsPerPage - 1) // itemsPerPage
startIndex = (self.page - 1) * itemsPerPage
endIndex = startIndex + itemsPerPage
currentPageItems = items[startIndex:endIndex]
for index, itemNumber in enumerate(currentPageItems):
item = itemManager.getItemstack(itemNumber)
display = itemManager.getItemDisplay(itemNumber)
if item is None:
item = Material.PAPER
self.set(index, item, display, data=itemNumber)
self.spawnSeparators(45, 53) # 填充最后一行默认黑色染色玻璃板
if self.page > 1:
self.set(45, Material.WHITE_STAINED_GLASS_PANE, u"§a上一页") # 上一页按钮
self.set(46, Material.WHEAT_SEEDS, u"§6>> §a§l查看草元素召唤物 §6<<")
self.set(47, Material.BLAZE_POWDER, u"§6>> §c§l查看火元素召唤物 §6<<")
self.set(48, Material.HEART_OF_THE_SEA, u"§6>> §3§l查看水元素召唤物 §6<<")
self.set(49, Material.COCOA_BEANS, u"§6>> §6§l查看地元素召唤物 §6<<")
self.set(50, Material.NETHER_STAR, u"§6>> §e§l查看雷元素召唤物 §6<<")
self.set(51, Material.SNOWBALL, u"§6>> §b§l查看冰元素召唤物 §6<<")
self.set(52, Material.FEATHER, u"§6>> §f§l查看风元素召唤物 §6<<")
if self.page < self.totalPages:
self.set(53, Material.WHITE_STAINED_GLASS_PANE, u"§a下一页") # 下一页按钮
# 记录玩家当前页码和筛选设置
playerPage[playerName] = {
"page": self.page,
"element": self.element
}
def onClick(self, e):
e.setCancelled(True)
clickInt = e.getSlot()
player = self.getPlayer()
playerName = player.getName()
playerPageInfo = playerPage.get(playerName, {"page": 1, "element": "none"})
currentPage = playerPageInfo["page"]
element = playerPageInfo["element"]
if clickInt == 45 and currentPage > 1:
MenuItems(player, page=currentPage - 1, element=element).openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 46:
MenuItems(player, page=1, element="grass").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 47:
MenuItems(player, page=1, element="fire").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 48:
MenuItems(player, page=1, element="water").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 49:
MenuItems(player, page=1, element="earth").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 50:
MenuItems(player, page=1, element="thunder").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 51:
MenuItems(player, page=1, element="ice").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 52:
MenuItems(player, page=1, element="wind").openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 53 and currentPage < self.totalPages:
MenuItems(player, page=currentPage + 1, element=element).openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt < 45:
if player.isOp():
item = e.getCurrentItem()
if item is not None:
guiValue = getGUIValue(item)
if guiValue:
itemId = guiValue
inv = player.getInventory()
if inv.firstEmpty() == -1: #如果背包满了
player.sendMessage(u"§d[灵气]§c背包已满无法获取召唤物")
player.playSound(player, Sound.ENTITY_VILLAGER_NO, 1.0, 1.0)
return
else:
player.getInventory().addItem(itemManager.getItemstack(itemId))
player.sendMessage(u"§d[灵气]§f成功获取 {}".format(itemManager.getItemDisplay(itemId)))
player.playSound(player, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0, 1.0)
class MenuReikiTable(GUIController):# 灵气台
def __init__(self, player, page=1):
super(MenuReikiTable, self).__init__(player)
self.page = page
self.setInfo("reiki.table", u"§0[灵气]灵气台 第{}".format(self.page))
self.setGUIManager(guiManager)
def render(self):
player = self.getPlayer()
playerName = player.getName()
blocks = list(blockManager.blockData.getKeys(False))
blocksLoc = {}
playerIsOP = player.isOp()
for id in blocks: #移除没有的台并记录坐标
blockLoc = blockManager.getTableLoc(id)
if blockLoc is None:
blocks.remove(id)
else:
blocksLoc[id] = blockLoc
blocksPerPage = 45 # 每页显示 45 个物品,最后一行用于控制
self.totalPages = (len(blocks) + blocksPerPage - 1) // blocksPerPage
startIndex = (self.page - 1) * blocksPerPage
endIndex = startIndex + blocksPerPage
currentPageBlocks = blocks[startIndex:endIndex]
for index, blockId in enumerate(currentPageBlocks):
blockLoc = blocksLoc[blockId]
display = blockManager.getTableName(blockId)
reikiTablePro = blockManager.getReikiTablePro(blockId)
blockX = blockLoc.getBlockX()
blockY = blockLoc.getBlockY()
blockZ = blockLoc.getBlockZ()
lores = [
u"§e坐标 §f{}, §f{}, §f{}".format(blockX, blockY, blockZ),
u"§e地利 §f{:.2f}".format(reikiTablePro)
]
if playerIsOP:
grass = blockManager.blockData.getInt("{}.grass".format(blockId), 0)
fire = blockManager.blockData.getInt("{}.fire".format(blockId), 0)
water = blockManager.blockData.getInt("{}.water".format(blockId), 0)
earth = blockManager.blockData.getInt("{}.earth".format(blockId), 0)
thunder = blockManager.blockData.getInt("{}.thunder".format(blockId), 0)
ice = blockManager.blockData.getInt("{}.ice".format(blockId), 0)
wind = blockManager.blockData.getInt("{}.wind".format(blockId), 0)
lores.append(u"§8- 以下信息仅管理员可见")
lores.append(u"§6ID §f{}".format(blockId))
lores.append(u"§6元素值 §a草{} §c火{} §3水{} §6地{} §e雷{} §b冰{} §f风{}".format(grass, fire, water, earth, thunder, ice, wind))
lores.append(u"§6")
lores.append(u"§6>> 点击传送至该灵气台 <<")
self.set(index, Material.END_PORTAL_FRAME, u"§a§l{}".format(display), *lores, data=blockId)
self.spawnSeparators(45, 53) # 填充最后一行默认黑色染色玻璃板
if self.page > 1:
self.set(45, Material.WHITE_STAINED_GLASS_PANE, u"§a上一页") # 上一页按钮
if self.page < self.totalPages:
self.set(53, Material.WHITE_STAINED_GLASS_PANE, u"§a下一页") # 下一页按钮
# 记录玩家当前页码
playerPage[playerName] = {
"page": self.page
}
def onClick(self, e):
e.setCancelled(True)
clickInt = e.getSlot()
player = self.getPlayer()
playerName = player.getName()
playerPageInfo = playerPage.get(playerName, {"page": 1})
currentPage = playerPageInfo["page"]
if clickInt == 45 and currentPage > 1:
MenuReikiTable(player, page=currentPage - 1).openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt == 53 and currentPage < self.totalPages:
MenuReikiTable(player, page=currentPage + 1).openWithRender()
player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0)
elif clickInt < 45:
if player.isOp(): #OP传送
item = e.getCurrentItem()
if item is not None:
guiValue = getGUIValue(item)
if guiValue:
blockId = guiValue
blockLoc = blockManager.getTableLoc(blockId)
if blockLoc is None:
player.sendMessage(u"§d[灵气]§c该灵气台不存在或已被移除")
player.playSound(player, Sound.ENTITY_VILLAGER_NO, 1.0, 1.0)
return
player.teleport(blockLoc)
player.sendMessage(u"§d[灵气]§f成功前往 {}".format(blockManager.getTableName(blockId)))
player.playSound(player, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0, 1.0)
def onInventoryClick(e): # 菜单点击
player = e.getWhoClicked()
worldName = player.getWorld().getName()
if worldName != WORLD_NAME:
return
inv = e.getClickedInventory()
if inv is None:
return
invHolder = inv.getHolder()
if isGUI(invHolder):
guiManager.get(e.getWhoClicked(), e.getClickedInventory().getHolder().getName()).onClick(e) # 菜单控制
return
cancelShiftClickFromPlayerInventory(e)
def onInventoryClose(e): # 菜单关闭
inv = e.getInventory()
if isGUI(inv.getHolder()):
guiManager.remove(e.getPlayer()) # 关闭菜单时清空存储的控制器
def stop(): # 程序卸载时
closeGuiForAll() # 关菜单
ps.listener.registerListener(onInventoryClick, InventoryClickEvent)
ps.listener.registerListener(onInventoryClose, InventoryCloseEvent)
ps.listener.registerListener(denyAllInventoryDrag, InventoryDragEvent)
def onPlayerInteract(event):
player = event.getPlayer()
worldName = player.getWorld().getName()
if worldName != WORLD_NAME:
return False
if event.getHand() == EquipmentSlot.OFF_HAND: #禁止副手触发
return False
clickedBlock = event.getClickedBlock()
if clickedBlock is None: #防止空指针
return False
if clickedBlock.getType() != Material.END_PORTAL_FRAME: #判断是否是灵气台
return False
blockLoc = clickedBlock.getLocation()
blockX = blockLoc.getBlockX()
blockY = blockLoc.getBlockY()
blockZ = blockLoc.getBlockZ()
blockId = None
for id in blockManager.blockData.getKeys(False):
x = blockManager.blockData.getInt("{}.x".format(id))
if blockX == x:
y = blockManager.blockData.getInt("{}.y".format(id))
if blockY == y:
z = blockManager.blockData.getInt("{}.z".format(id))
if blockZ == z:
blockId = id
break
if blockId is None:
return False
playerManager = PlayerManager(player)
item = event.getItem()
guiValue = getGUIValue(item)
if guiValue is not None:
reiki, key = guiValue.split(':')
if reiki == u"reiki":
if key == u"DANDELION":
result = playerManager.reikiCall(blockId, key)
if result:
item.setAmount(item.getAmount()-1)
return
MenuReikiInfo(player, blockId).openWithRender()
ps.listener.registerListener(onPlayerInteract, PlayerInteractEvent)
def reikiCommand(sender, label, args):
if isinstance(sender, Player):
if sender.isOp():
if sender.getWorld().getName() != WORLD_NAME:
sender.sendMessage(u"§d[灵气]§f请在世界 §e{} §f中使用此命令".format(WORLD_NAME))
return False
playerManager = PlayerManager(sender)
if len(args) < 1:
sender.sendMessage(u"§d[灵气] §a管理员命令帮助")
sender.sendMessage(u"§d[灵气] §f/reiki add §e- 创建灵气台")
sender.sendMessage(u"§d[灵气] §f/reiki del §e- 删除灵气台")
sender.sendMessage(u"§d[灵气] §f/reiki list §e- 查看所有灵气台")
sender.sendMessage(u"§d[灵气] §f/reiki item §e- 查看所有召唤物")
sender.sendMessage(u"§d[灵气] §f/reiki set element <元素名> <值> §e- 设置灵气台元素值")
sender.sendMessage(u"§d[灵气] §f/reiki set name <名称> §e- 设置灵气台名称")
return False
elif args[0] == u"add": #目视传送门框架,创建灵气台
blockLoc = playerManager.getTargetFrameLocation()
if blockLoc is not None:
blockId = blockManager.createReikiTable(blockLoc)
if blockId is False:
sender.sendMessage(u"§d[灵气]§f该位置已经有灵气台了")
return False
else:
sender.sendMessage(u"§d[灵气]§f成功创建ID为{}的灵气台".format(blockId))
return True
else:
sender.sendMessage(u"§d[灵气]§f请看着一个末地传送门框架")
return False
elif args[0] == u"del": #目视传送门框架,删除灵气台
blockLoc = playerManager.getTargetFrameLocation()
if blockLoc is not None:
blockId = blockManager.getLocTable(blockLoc)
if blockId is None:
sender.sendMessage(u"§d[灵气]§f该位置没有灵气台")
return False
result = blockManager.delReikiTable(blockId)
if result is False:
sender.sendMessage(u"§d[灵气]§f未找到该灵气台")
return False
else:
sender.sendMessage(u"§d[灵气]§f成功删除灵气台")
return True
else:
sender.sendMessage(u"§d[灵气]§f请看着一个末地传送门框架")
return False
elif args[0] == u"list":
MenuReikiTable(sender).openWithRender()
return True
elif args[0] == u"item":
MenuItems(sender).openWithRender()
return True
elif args[0] == u"set": #目视传送门框架,设置灵气台
if len(args) > 2:
blockLoc = playerManager.getTargetFrameLocation()
if blockLoc is not None:
blockId = blockManager.getLocTable(blockLoc)
if blockId is None:
sender.sendMessage(u"§d[灵气]§f该位置没有灵气台")
return False
setType = args[1]
if setType == u"element":
element = args[2]
if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]:
sender.sendMessage(u"§d[灵气]§f元素不存在")
return False
value = args[3]
try:
value = int(value)
except ValueError:
sender.sendMessage(u"§d[灵气]§f数值必须为整数")
return False
result = blockManager.setTableElement(blockId, element, value)
if result is False:
sender.sendMessage(u"§d[灵气]§f设置失败")
return False
else:
sender.sendMessage(u"§d[灵气]§f成功设置元素值")
return True
elif setType == u"name":
name = u" ".join(args[2:])
result = blockManager.setTableName(blockId, name)
if result is False:
sender.sendMessage(u"§d[灵气]§f设置失败")
return False
else:
sender.sendMessage(u"§d[灵气]§f成功设置名称")
return True
else:
sender.sendMessage(u"§d[灵气]§f无效的参数")
else:
sender.sendMessage(u"§d[灵气]§f请看着一个末地传送门框架")
else:
sender.sendMessage(u"§d[灵气]§f请输入参数")
return False
else:
sender.sendMessage(u"§d[灵气]§f无效的参数")
return False
return False
ps.command.registerCommand(reikiCommand, "reiki")