This commit is contained in:
nossr50 2011-08-28 17:57:19 -07:00
parent 470089c9b2
commit 8596e10214
12 changed files with 155 additions and 77 deletions

View File

@ -1,5 +1,13 @@
Changelog: Changelog:
#Versions without changelogs probably had very small misc fixes, like tweaks to the source code #Versions without changelogs probably had very small misc fixes, like tweaks to the source code
Version 1.1.12
mcMMO now downloads files when you join the server to provide the best experience
mcMMO now uses a brand new Party HUD by Rycochet (from his mmoParty plugin)
Fixed the xpbar and xpicon settings in config to work properly
Fixed infinite HP exploit with Herbalism
Fixed bug where herbalism would heal out of the players normal health range
Fixed bug where entering ':' into your party name caused stat loss among other things
Version 1.1.11 Version 1.1.11
mcMMO now properly cancels its Async taks when disabled mcMMO now properly cancels its Async taks when disabled
Fixed newly generated configs using 2 instead of 1 for skill multipliers Fixed newly generated configs using 2 instead of 1 for skill multipliers

View File

@ -1167,7 +1167,6 @@ public class Commands
if(PP.inParty() && (!Pinstance.isParty(PP.getParty()) || !Pinstance.isInParty(player, PP))) if(PP.inParty() && (!Pinstance.isParty(PP.getParty()) || !Pinstance.isInParty(player, PP)))
{ {
Pinstance.addToParty(player, PP, PP.getParty(), false); Pinstance.addToParty(player, PP, PP.getParty(), false);
} }
if(args.length == 0 && !PP.inParty()) if(args.length == 0 && !PP.inParty())

View File

@ -106,6 +106,7 @@ public class HUDmmo
Color green = new Color(0, 1f, 0, 1f); Color green = new Color(0, 1f, 0, 1f);
Color background = new Color((float)LoadProperties.xpbackground_r, (float)LoadProperties.xpbackground_g, (float)LoadProperties.xpbackground_b, 1f); Color background = new Color((float)LoadProperties.xpbackground_r, (float)LoadProperties.xpbackground_g, (float)LoadProperties.xpbackground_b, 1f);
Color darkbg = new Color(0.2f, 0.2f, 0.2f, 1f); Color darkbg = new Color(0.2f, 0.2f, 0.2f, 1f);
xpicon = new GenericTexture(); xpicon = new GenericTexture();
xpbar = new GenericGradient(); xpbar = new GenericGradient();
xpfill = new GenericGradient(); xpfill = new GenericGradient();
@ -129,12 +130,18 @@ public class HUDmmo
xpbg.setWidth(126).setHeight(2).setX(150).setY(11); xpbg.setWidth(126).setHeight(2).setX(150).setY(11);
xpbg.setBottomColor(background).setTopColor(background).setPriority(RenderPriority.Low).setDirty(true); xpbg.setBottomColor(background).setTopColor(background).setPriority(RenderPriority.Low).setDirty(true);
if(LoadProperties.xpbar)
{
sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpbar); sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpbar);
sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpfill); sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpfill);
sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpbg); sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpbg);
if(LoadProperties.xpicon)
{
sPlayer.getMainScreen().attachWidget(plugin, (GenericTexture)xpicon); sPlayer.getMainScreen().attachWidget(plugin, (GenericTexture)xpicon);
sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpicon_bg); sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpicon_bg);
}
sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpicon_border); sPlayer.getMainScreen().attachWidget(plugin, (GenericGradient)xpicon_border);
}
sPlayer.getMainScreen().setDirty(true); sPlayer.getMainScreen().setDirty(true);
} }
@ -144,7 +151,7 @@ public class HUDmmo
//Setup xp bar //Setup xp bar
xpbar = new GenericTexture(); xpbar = new GenericTexture();
if(LoadProperties.xpicon) if(LoadProperties.xpbar && LoadProperties.xpicon)
{ {
xpicon = new GenericTexture(); xpicon = new GenericTexture();
@ -157,11 +164,13 @@ public class HUDmmo
sPlayer.getMainScreen().attachWidget(plugin, xpicon); sPlayer.getMainScreen().attachWidget(plugin, xpicon);
} }
if(LoadProperties.xpbar)
{
((GenericTexture)xpbar).setUrl(LoadProperties.web_url+"HUD/Standard/xpbar_inc000.png"); ((GenericTexture)xpbar).setUrl(LoadProperties.web_url+"HUD/Standard/xpbar_inc000.png");
xpbar.setX(LoadProperties.xpbar_x).setY(LoadProperties.xpbar_y).setHeight(8).setWidth(256); xpbar.setX(LoadProperties.xpbar_x).setY(LoadProperties.xpbar_y).setHeight(8).setWidth(256);
sPlayer.getMainScreen().attachWidget(plugin, xpbar); sPlayer.getMainScreen().attachWidget(plugin, xpbar);
}
sPlayer.getMainScreen().setDirty(true); sPlayer.getMainScreen().setDirty(true);
} }
@ -170,7 +179,7 @@ public class HUDmmo
//Setup xp bar //Setup xp bar
xpbar = new GenericTexture(); xpbar = new GenericTexture();
if(LoadProperties.xpicon) if(LoadProperties.xpbar && LoadProperties.xpicon)
{ {
xpicon = new GenericTexture(); xpicon = new GenericTexture();
@ -183,16 +192,22 @@ public class HUDmmo
sPlayer.getMainScreen().attachWidget(plugin, xpicon); sPlayer.getMainScreen().attachWidget(plugin, xpicon);
} }
if(LoadProperties.xpbar)
{
((GenericTexture)xpbar).setUrl(LoadProperties.web_url+"HUD/Standard/xpbar_inc000.png"); ((GenericTexture)xpbar).setUrl(LoadProperties.web_url+"HUD/Standard/xpbar_inc000.png");
xpbar.setX(center_x-64).setY(LoadProperties.xpbar_y).setHeight(4).setWidth(128); xpbar.setX(center_x-64).setY(LoadProperties.xpbar_y).setHeight(4).setWidth(128);
sPlayer.getMainScreen().attachWidget(plugin, xpbar); sPlayer.getMainScreen().attachWidget(plugin, xpbar);
}
sPlayer.getMainScreen().setDirty(true); sPlayer.getMainScreen().setDirty(true);
} }
private void updateXpBarStandard(Player player, PlayerProfile PP) private void updateXpBarStandard(Player player, PlayerProfile PP)
{ {
if(!LoadProperties.xpbar)
return;
SkillType theType = null; SkillType theType = null;
if(PP.getXpBarLocked()) if(PP.getXpBarLocked())
@ -214,6 +229,8 @@ public class HUDmmo
private void updateXpBarRetro(Player player, PlayerProfile PP) private void updateXpBarRetro(Player player, PlayerProfile PP)
{ {
if(!LoadProperties.xpbar)
return;
SkillType theType = null; SkillType theType = null;
if(PP.getXpBarLocked() && PP.getSkillLock() != null) if(PP.getXpBarLocked() && PP.getSkillLock() != null)

View File

@ -72,8 +72,6 @@ public class PlayerProfile
} }
} }
mana = getMaxMana();
playername = player.getName(); playername = player.getName();
if (LoadProperties.useMySQL) if (LoadProperties.useMySQL)
{ {
@ -548,12 +546,6 @@ public class PlayerProfile
{ {
return mana; return mana;
} }
public int getMaxMana()
{
if(skills.get(SkillType.SORCERY) < 50)
return 5;
return skills.get(SkillType.SORCERY) / 10;
}
public void setDyeChanged(Boolean bool) public void setDyeChanged(Boolean bool)
{ {
dyeChanged = bool; dyeChanged = bool;
@ -956,9 +948,6 @@ public class PlayerProfile
case AXES: case AXES:
xp=(int) (xp/LoadProperties.axesxpmodifier); xp=(int) (xp/LoadProperties.axesxpmodifier);
break; break;
case SORCERY:
xp=(int) (xp/LoadProperties.sorceryxpmodifier);
break;
} }
xp=xp*LoadProperties.xpGainMultiplier; xp=xp*LoadProperties.xpGainMultiplier;
skillsXp.put(skillType, skillsXp.get(skillType)+xp); skillsXp.put(skillType, skillsXp.get(skillType)+xp);
@ -981,7 +970,6 @@ public class PlayerProfile
skillsXp.put(SkillType.UNARMED, skillsXp.get(SkillType.UNARMED)-newvalue); skillsXp.put(SkillType.UNARMED, skillsXp.get(SkillType.UNARMED)-newvalue);
skillsXp.put(SkillType.EXCAVATION, skillsXp.get(SkillType.EXCAVATION)-newvalue); skillsXp.put(SkillType.EXCAVATION, skillsXp.get(SkillType.EXCAVATION)-newvalue);
skillsXp.put(SkillType.AXES, skillsXp.get(SkillType.AXES)-newvalue); skillsXp.put(SkillType.AXES, skillsXp.get(SkillType.AXES)-newvalue);
skillsXp.put(SkillType.SORCERY, skillsXp.get(SkillType.SORCERY)-newvalue);
} else { } else {
skillsXp.put(skillType, skillsXp.get(skillType)-newvalue); skillsXp.put(skillType, skillsXp.get(skillType)-newvalue);
} }
@ -1013,7 +1001,6 @@ public class PlayerProfile
skills.put(SkillType.UNARMED, newvalue); skills.put(SkillType.UNARMED, newvalue);
skills.put(SkillType.EXCAVATION, newvalue); skills.put(SkillType.EXCAVATION, newvalue);
skills.put(SkillType.AXES, newvalue); skills.put(SkillType.AXES, newvalue);
skills.put(SkillType.SORCERY, newvalue);
skillsXp.put(SkillType.TAMING, 0); skillsXp.put(SkillType.TAMING, 0);
skillsXp.put(SkillType.MINING, 0); skillsXp.put(SkillType.MINING, 0);
@ -1026,7 +1013,6 @@ public class PlayerProfile
skillsXp.put(SkillType.UNARMED, 0); skillsXp.put(SkillType.UNARMED, 0);
skillsXp.put(SkillType.EXCAVATION, 0); skillsXp.put(SkillType.EXCAVATION, 0);
skillsXp.put(SkillType.AXES, 0); skillsXp.put(SkillType.AXES, 0);
skillsXp.put(SkillType.SORCERY, 0);
} else { } else {
skills.put(skillType, newvalue); skills.put(skillType, newvalue);
skillsXp.put(skillType, newvalue); skillsXp.put(skillType, newvalue);

View File

@ -10,7 +10,6 @@ public enum SkillType
HERBALISM, HERBALISM,
MINING, MINING,
REPAIR, REPAIR,
SORCERY,
SWORDS, SWORDS,
TAMING, TAMING,
UNARMED, UNARMED,

View File

@ -205,6 +205,11 @@ public class mcPlayerListener extends PlayerListener
/* /*
* HERBALISM MODIFIERS * HERBALISM MODIFIERS
*/ */
if(action == Action.RIGHT_CLICK_BLOCK && !m.abilityBlockCheck(event.getClickedBlock()))
{
return;
}
if(mcPermissions.getInstance().herbalism(player)) if(mcPermissions.getInstance().herbalism(player))
{ {
Herbalism.breadCheck(player, player.getItemInHand()); Herbalism.breadCheck(player, player.getItemInHand());

View File

@ -36,6 +36,8 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.getspout.spoutapi.SpoutManager;
import org.getspout.spoutapi.player.FileManager;
public class mcMMO extends JavaPlugin public class mcMMO extends JavaPlugin
@ -140,6 +142,18 @@ public class mcMMO extends JavaPlugin
{ {
SpoutStuff.setupSpoutConfigs(); SpoutStuff.setupSpoutConfigs();
SpoutStuff.registerCustomEvent(); SpoutStuff.registerCustomEvent();
FileManager FM = SpoutManager.getFileManager();
FM.addToPreLoginCache(this, SpoutStuff.getFiles());
Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this,
new Runnable() {
@Override
public void run() {
mmoHelper.updateAll();
}
}, 20, 20);
} }
PluginDescriptionFile pdfFile = this.getDescription(); PluginDescriptionFile pdfFile = this.getDescription();
@ -156,15 +170,6 @@ public class mcMMO extends JavaPlugin
System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!" ); System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!" );
Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask(this, mcMMO_Timer, 0, 20); Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask(this, mcMMO_Timer, 0, 20);
Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this,
new Runnable() {
@Override
public void run() {
mmoHelper.updateAll();
}
}, 20, 20);
} }
public PlayerProfile getPlayerProfile(Player player) public PlayerProfile getPlayerProfile(Player player)

View File

@ -143,7 +143,7 @@ public class Party
for(Player p : Bukkit.getServer().getOnlinePlayers()) for(Player p : Bukkit.getServer().getOnlinePlayers())
{ {
if(p.isOnline() && player != null && p != null) if(p.isOnline())
{ {
if(inSameParty(player, p)) if(inSameParty(player, p))
{ {
@ -214,12 +214,16 @@ public class Party
} }
public void addToParty(Player player, PlayerProfile PP, String newParty, Boolean invite) { public void addToParty(Player player, PlayerProfile PP, String newParty, Boolean invite) {
newParty = newParty.replace(":", ".");
addToParty(player, PP, newParty, invite, null); addToParty(player, PP, newParty, invite, null);
} }
public void addToParty(Player player, PlayerProfile PP, String newParty, Boolean invite, String password) public void addToParty(Player player, PlayerProfile PP, String newParty, Boolean invite, String password)
{ {
//Fix for FFS
newParty = newParty.replace(":", ".");
//Don't care about passwords on invites //Don't care about passwords on invites
if(!invite) if(!invite)
{ {
@ -373,9 +377,14 @@ public class Party
} }
public boolean isPartyLeader(Player player, String partyName) { public boolean isPartyLeader(Player player, String partyName) {
if(this.partyPlayers.get(partyName) != null)
{
if(this.partyPlayers.get(partyName).get(player.getName()) == null) return false; if(this.partyPlayers.get(partyName).get(player.getName()) == null) return false;
return this.partyPlayers.get(partyName).get(player.getName()); return this.partyPlayers.get(partyName).get(player.getName());
} }
else
return false;
}
public boolean isPartyLocked(String partyName) { public boolean isPartyLocked(String partyName) {
if(this.partyLocks.get(partyName) == null) return false; if(this.partyLocks.get(partyName) == null) return false;

View File

@ -309,66 +309,82 @@ public class Herbalism
{ {
PlayerProfile PP = Users.getProfile(player); PlayerProfile PP = Users.getProfile(player);
int herbalism = PP.getSkillLevel(SkillType.HERBALISM); int herbalism = PP.getSkillLevel(SkillType.HERBALISM);
int heal = 0;
if(is.getTypeId() == 297) if(is.getTypeId() == 297)
{ {
if(herbalism >= 50 && herbalism < 150) if(herbalism >= 50 && herbalism < 150)
{ {
player.setHealth(player.getHealth() + 1); heal = 1;
} else if (herbalism >= 150 && herbalism < 250) } else if (herbalism >= 150 && herbalism < 250)
{ {
player.setHealth(player.getHealth() + 2); heal = 2;
} else if (herbalism >= 250 && herbalism < 350) } else if (herbalism >= 250 && herbalism < 350)
{ {
player.setHealth(player.getHealth() + 3); heal = 3;
} else if (herbalism >= 350 && herbalism < 450) } else if (herbalism >= 350 && herbalism < 450)
{ {
player.setHealth(player.getHealth() + 4); heal = 4;
} else if (herbalism >= 450 && herbalism < 550) } else if (herbalism >= 450 && herbalism < 550)
{ {
player.setHealth(player.getHealth() + 5); heal = 5;
} else if (herbalism >= 550 && herbalism < 650) } else if (herbalism >= 550 && herbalism < 650)
{ {
player.setHealth(player.getHealth() + 6); heal = 6;
} else if (herbalism >= 650 && herbalism < 750) } else if (herbalism >= 650 && herbalism < 750)
{ {
player.setHealth(player.getHealth() + 7); heal = 7;
} else if (herbalism >= 750) } else if (herbalism >= 750)
{ {
player.setHealth(player.getHealth() + 8); heal = 8;
} }
if(player.getHealth()+heal > 20)
{
player.setHealth(20);
}
else
player.setHealth(player.getHealth()+heal);
} }
} }
public static void stewCheck(Player player, ItemStack is) public static void stewCheck(Player player, ItemStack is)
{ {
PlayerProfile PP = Users.getProfile(player); PlayerProfile PP = Users.getProfile(player);
int herbalism = PP.getSkillLevel(SkillType.HERBALISM); int herbalism = PP.getSkillLevel(SkillType.HERBALISM);
int heal = 0;
if(is.getTypeId() == 282) if(is.getTypeId() == 282)
{ {
if(herbalism >= 50 && herbalism < 150) if(herbalism >= 50 && herbalism < 150)
{ {
player.setHealth(player.getHealth() + 1); heal = 1;
} else if (herbalism >= 150 && herbalism < 250) } else if (herbalism >= 150 && herbalism < 250)
{ {
player.setHealth(player.getHealth() + 2); heal = 2;
} else if (herbalism >= 250 && herbalism < 350) } else if (herbalism >= 250 && herbalism < 350)
{ {
player.setHealth(player.getHealth() + 3); heal = 3;
} else if (herbalism >= 350 && herbalism < 450) } else if (herbalism >= 350 && herbalism < 450)
{ {
player.setHealth(player.getHealth() + 4); heal = 4;
} else if (herbalism >= 450 && herbalism < 550) } else if (herbalism >= 450 && herbalism < 550)
{ {
player.setHealth(player.getHealth() + 5); heal = 5;
} else if (herbalism >= 550 && herbalism < 650) } else if (herbalism >= 550 && herbalism < 650)
{ {
player.setHealth(player.getHealth() + 6); heal = 6;
} else if (herbalism >= 650 && herbalism < 750) } else if (herbalism >= 650 && herbalism < 750)
{ {
player.setHealth(player.getHealth() + 7); heal = 7;
} else if (herbalism >= 750) } else if (herbalism >= 750)
{ {
player.setHealth(player.getHealth() + 8); heal = 8;
} }
if(player.getHealth()+heal > 20)
{
player.setHealth(20);
}
else
player.setHealth(player.getHealth()+heal);
} }
} }
} }

View File

@ -1,5 +1,6 @@
package com.gmail.nossr50.spout; package com.gmail.nossr50.spout;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -61,6 +62,46 @@ public class SpoutStuff
keypress = Keyboard.KEY_M; keypress = Keyboard.KEY_M;
} }
} }
public static ArrayList<String> getFiles()
{
ArrayList<String> files = new ArrayList<String>();
int x = 0;
//XP BAR
while(x < 255)
{
if(x < 10)
{
files.add(LoadProperties.web_url+"HUD/Standard/xpbar_inc00"+x+".png");
} else if (x < 100)
{
files.add(LoadProperties.web_url+"HUD/Standard/xpbar_inc0"+x+".png");
} else
{
files.add(LoadProperties.web_url+"HUD/Standard/xpbar_inc"+x+".png");
}
x++;
}
//Standard XP Icons
for(SkillType y : SkillType.values())
{
if(y == SkillType.ALL)
continue;
files.add(LoadProperties.web_url+"HUD/Standard/"+m.getCapitalized(y.toString())+".png");
files.add(LoadProperties.web_url+"HUD/Retro/"+m.getCapitalized(y.toString())+"_r.png");
}
//Blank icons
files.add(LoadProperties.web_url+"HUD/Standard/Icon.png");
files.add(LoadProperties.web_url+"HUD/Retro/Icon_r.png");
//Repair SFX
files.add(LoadProperties.web_url+"/Sound/repair.wav");
//Level SFX
files.add(LoadProperties.web_url+"/Sound/level.wav");
return files;
}
public static void registerCustomEvent() public static void registerCustomEvent()
{ {
Bukkit.getServer().getPluginManager().registerEvent(Event.Type.CUSTOM_EVENT, spoutListener, Priority.Normal, plugin); Bukkit.getServer().getPluginManager().registerEvent(Event.Type.CUSTOM_EVENT, spoutListener, Priority.Normal, plugin);
@ -86,8 +127,6 @@ public class SpoutStuff
return new Color((float)LoadProperties.mining_r, (float)LoadProperties.mining_g, (float)LoadProperties.mining_b, 1f); return new Color((float)LoadProperties.mining_r, (float)LoadProperties.mining_g, (float)LoadProperties.mining_b, 1f);
case REPAIR: case REPAIR:
return new Color((float)LoadProperties.repair_r, (float)LoadProperties.repair_g, (float)LoadProperties.repair_b, 1f); return new Color((float)LoadProperties.repair_r, (float)LoadProperties.repair_g, (float)LoadProperties.repair_b, 1f);
case SORCERY:
return new Color(0.3f, 0.3f, 0.75f, 1f);
case SWORDS: case SWORDS:
return new Color((float)LoadProperties.swords_r, (float)LoadProperties.swords_g, (float)LoadProperties.swords_b, 1f); return new Color((float)LoadProperties.swords_r, (float)LoadProperties.swords_g, (float)LoadProperties.swords_b, 1f);
case TAMING: case TAMING:
@ -311,9 +350,6 @@ public class SpoutStuff
Material mat = null; Material mat = null;
switch(skillType) switch(skillType)
{ {
case SORCERY:
mat = Material.PORTAL;
break;
case TAMING: case TAMING:
switch(getNotificationTier(PP.getSkillLevel(skillType))) switch(getNotificationTier(PP.getSkillLevel(skillType)))
{ {

View File

@ -199,22 +199,20 @@ public class mmoHelper
int index = 0; int index = 0;
Widget[] bars = container.getChildren(); Widget[] bars = container.getChildren();
for (String name : Party.getInstance().getPartyMembersByName(player).meFirst(player.getName())) for (String name : Party.getInstance().getPartyMembersByName(player).meFirst(player.getName()))
{
if(Bukkit.getServer().getPlayer(name).isOnline())
{ {
GenericLivingEntity bar; GenericLivingEntity bar;
if (index >= bars.length) { if (index >= bars.length)
{
container.addChild(bar = new GenericLivingEntity()); container.addChild(bar = new GenericLivingEntity());
} else { } else {
bar = (GenericLivingEntity)bars[index]; bar = (GenericLivingEntity)bars[index];
} }
bar.setEntity(name, Party.getInstance().isPartyLeader(player, Users.getProfile(player).getParty()) ? ChatColor.GREEN + "@" : ""); bar.setEntity(name, Party.getInstance().isPartyLeader(Bukkit.getServer().getPlayer(name), Users.getProfile(Bukkit.getServer().getPlayer(name)).getParty()) ? ChatColor.GREEN + "@" : "");
bar.setTargets(show_pets ? getPets(Bukkit.getServer().getPlayer(name)) : null); bar.setTargets(show_pets ? getPets(Bukkit.getServer().getPlayer(name)) : null);
index++; index++;
} }
}
while (index < bars.length) { while (index < bars.length) {
container.removeChild(bars[index--]); container.removeChild(bars[index++]);
} }
container.updateLayout(); container.updateLayout();
} }

View File

@ -1,6 +1,6 @@
name: mcMMO name: mcMMO
main: com.gmail.nossr50.mcMMO main: com.gmail.nossr50.mcMMO
version: 1.1.11 version: 1.1.12
softdepend: [Spout] softdepend: [Spout]
commands: commands:
mchud: mchud: