I'm trying to make it so when someone with the role "Owner" types the mute command, it takes the person they #mentioned and gives them the "Muted" role.
The rest of the code works on it's own, the only part that is not working is the line
event.getGuild().addRoleToMember(member,event.getGuild().getRoleById(0)).complete();
and the variable "member" is defined by
Member member = event.getGuild().getMemberById(mentionid);
The full chunk of code is:
package radishmouse.FoodWorld.Events;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import radishmouse.FoodWorld.FoodWorld;
public class GuildMessageReceived extends ListenerAdapter {
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
String[] args = event.getMessage().getContentRaw().split("\\s+");
if (args[0].equalsIgnoreCase(FoodWorld.prefix + "mute")) {
if (hasRole("Owner", event)) {
if (args.length == 2) {
String mentionid = args[1].replace("<#!", "").replace(">", "");
Member member = event.getGuild().getMemberById(mentionid);
event.getGuild().addRoleToMember(member, event.getGuild().getRoleById(0)).complete();
EmbedBuilder msg = FoodWorld.sendMessage(null, "idk " + mentionid + member, "Blue");
event.getChannel().sendMessageEmbeds(msg.build()).queue();
}
else {
EmbedBuilder msg = FoodWorld.sendMessage("Specify Who To Mute", "Usage: " + FoodWorld.prefix + "mute [#mention who to mute]", "Blue");
event.getChannel().sendMessageEmbeds(msg.build()).queue();
}
}
}
/* If the bot ever sends a message, then add a ❌ reaction so users can delete that message */
if (event.getAuthor().equals(event.getJDA().getSelfUser())) {
event.getMessage().addReaction("❌").queue();
}
}
private boolean hasRole(String string, GuildMessageReceivedEvent event) {
Boolean toReturn = false;
for(int i=0; i < event.getMember().getRoles().size(); i++){
if("Owner".equals(event.getMember().getRoles().get(i).getName())){
toReturn = true;
}
}
return toReturn;
}
For reference, I'm following this tutorial on youtube: tutorial.
I'm not the most familiar with JDA and don't know how this would be done in an easier way.
Instead of parsing the string:
String mentionid = args[1].replace("<#!", "").replace(">", "");
Member member = event.getGuild().getMemberById(mentionid);
Use getMentionedMembers:
List<Member> mentions = event.getMessage().getMentionedMembers();
if (mentions.isEmpty()) {
EmbedBuilder msg = FoodWorld.sendMessage("Specify Who To Mute", "Usage: " + FoodWorld.prefix + "mute [#mention who to mute]", "Blue");
event.getChannel().sendMessageEmbeds(msg.build()).queue();
} else {
Member member = mentions.get(0);
event.getGuild().addRoleToMember(member, event.getGuild().getRoleById(0)).queue();
EmbedBuilder msg = FoodWorld.sendMessage(null, "idk " + member.getId() + member, "Blue");
event.getChannel().sendMessageEmbeds(msg.build()).queue();
}
I'm using a java server to facilitate online multiplayer in my game made with GameMaker Studio, the players will send data to the java server which will process the data and send it to the players. The problem is that when a player with a slow internet connection is not being able to handle the amount of data being send to it, it will cause the server to freeze for all players (the server will no longer process any data send by other players).
I have simulated slow internet speeds by using NetLimiter and setting the download speed of one laptop at 5 kb/s, while maintaining proper speed at other laptops. I have tried to send ACK packets from the java server to the client and if it doesn't respond in 1 second no more data will be send to that client (and eventually the client will be kicked). This has reduced the chance of freezing the server, but it will still happen occasionally.
Main.java
import java.net.Socket;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import java.io.IOException;
import java.util.HashMap;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;
public class Main
{
static ServerSocket serverSocket_;
static HashMap<String, ServerInformation> servers_;
static int verboseLevel_;
static int threadTimeout_;
static int masterPort_;
static int serverNumber_;
static int socketTimeOut_;
static {
Main.serverSocket_ = null;
Main.servers_ = new HashMap<String, ServerInformation>();
Main.verboseLevel_ = 5;
Main.threadTimeout_ = 10;
Main.masterPort_ = 6510;
Main.serverNumber_ = 1;
Main.socketTimeOut_ = 6000;
}
public static void main(final String[] args) {
try {
setupServerAndCleanup(Main.masterPort_);
while (true) {
handleIncomingConnection();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
static void setupServerAndCleanup(final int port) throws IOException {
(Main.serverSocket_ = new ServerSocket()).setReuseAddress(true);
Main.serverSocket_.bind(new InetSocketAddress(Main.masterPort_));
System.out.println("Server socket up and running on port " + Main.masterPort_);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
if (Main.serverSocket_ != null) {
try {
Main.serverSocket_.close();
System.out.println("Server socket closed, port released");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}));
}
static void handleIncomingConnection() throws IOException {
final Socket clientSocket = Main.serverSocket_.accept();
clientSocket.setSoTimeout(Main.socketTimeOut_);
final ClientThread client = new ClientThread(clientSocket);
client.start();
}
}
ClientThread.java
Case 1 is the part dealing with sending data to the clients, in particular this line:
thread2.out_.print(msg);
If more data is being send than one client can handle the server will freeze for all other clients as well.
import java.util.Iterator;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class ClientThread extends Thread
{
Socket clientSocket_;
String clientIp_;
String serverIp_;
ServerInformation server_;
PrintWriter out_;
BufferedReader in_;
boolean prepareTermination_;
boolean terminated_;
private static final Pattern numberPattern;
static {
numberPattern = Pattern.compile("\\d+");
}
public ClientThread(final Socket sock) {
this.clientSocket_ = sock;
this.clientIp_ = this.clientSocket_.getRemoteSocketAddress().toString();
this.serverIp_ = null;
this.server_ = null;
this.prepareTermination_ = false;
this.terminated_ = false;
}
#Override
public void run() {
try {
this.out_ = new PrintWriter(this.clientSocket_.getOutputStream(), true);
this.in_ = new BufferedReader(new InputStreamReader(this.clientSocket_.getInputStream()));
long lastActionTime = System.currentTimeMillis();
while (true) {
if (this.in_.ready() || System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
if (System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
//this.logDebugMessage(3, "Thread was killed due to prolonged inactivity (" + Main.threadTimeout_ + " seconds)");
this.terminateThread();
return;
}
final String tempInputLine;
if(((tempInputLine = this.in_.readLine()) == null )){
this.terminateThread(); //end thread
return;
}
else
{
lastActionTime = System.currentTimeMillis();
final String inputLine = tempInputLine.trim();
if (ClientThread.numberPattern.matcher(inputLine).matches()){
final int val = Integer.parseInt(inputLine);
switch (val) {
case 1: { //send data to other players
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int j = 0; j < parseCount; ++j) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(msg);
thread2.out_.flush();
}
}
//this.logDebugMessage(5, "Packet for others: '" + msg.toString() + "'");
break;
}
case 2: { //remove game server
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(this.server_.ip_);
this.serverIp_ = null;
for (final ClientThread thread : this.server_.ipToClientThread_.values()) {
thread.prepareTermination_ = true;
}
this.terminateThread();
return;
}
case 3: { //connect new client
final String ipServer = this.in_.readLine().trim();
final String ipClient = this.in_.readLine().trim();
this.logDebugMessage(1, "A client wishes to connect to a server, client: " + ipClient + ", server: " + ipServer);
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
if (info == null) {
System.out.println("Connection to the server failed, no such server in the server list");
this.out_.print("*" + 1 + "|" + 1 + "~" + "|");
this.out_.flush();
break;
}
this.server_ = info;
this.server_.ipToClientThread_.put(ipClient, this);
this.logDebugMessage(1, "Connection success");
this.logDebugMessage(5,"Map: " + this.server_.ipToClientThread_);
this.out_.print("*" + 1 + "|" + 2 + "~" + "|");
this.out_.flush();
break;
}
case 4: { //disconnect client
final String ipClient = this.in_.readLine().trim();
this.server_.ipToClientThread_.remove(ipClient);
this.logDebugMessage(1, String.valueOf(ipClient) + " disconnected from the server at " + this.server_.ip_);
this.serverIp_ = null;
this.terminateThread();
return;
}
case 5: { //host create new game
if (Main.serverNumber_ > 1000000) {
Main.serverNumber_ = 10;
}
Main.serverNumber_ += 1;
final String ipServer = Integer.toString(Main.serverNumber_); //unique server number
final String ipHost = this.in_.readLine().trim(); //host
final String name = this.in_.readLine().trim(); //Server name
final String description = this.in_.readLine().trim(); //class
final String servervar1 = this.in_.readLine().trim(); //max players
final String servervar3 = this.in_.readLine().trim(); //current lap
final String servervar4 = this.in_.readLine().trim(); //total laps
final String servervar5 = this.in_.readLine().trim(); //status
final String servervar6 = this.in_.readLine().trim(); //Password
final String servervar7 = this.in_.readLine().trim(); //Online version
final String servervar8 = this.in_.readLine().trim(); //Game server
final long servervar9 = System.currentTimeMillis(); //server creation time
//this.logDebugMessage(1, "A game server has been registered, ip: " + ipServer + ", name: " + name + ", description: " + description + ", servervar1: " + servervar1);
final ServerInformation gameServer = new ServerInformation(name, servervar1, servervar3, servervar4, servervar5, servervar6, servervar7, servervar8, servervar9, ipHost, ipServer, this.clientSocket_, this.out_, this.in_);
gameServer.description_ = description;
gameServer.ipToClientThread_.put(ipHost, this);
this.server_ = gameServer;
Main.servers_.put(ipServer, gameServer);
this.serverIp_ = ipServer;
break;
}
default: {
this.logDebugMessage(0, "Unrecognized case: '" + inputLine + "', " + val);
break;
}
}
}
else if (inputLine.length() > 0) {
this.logDebugMessage(0, "Unformated '" + inputLine + "'");
if (this.server_ != null) {
this.server_.out_.print(inputLine);
this.server_.out_.flush();
}
}
if (this.prepareTermination_) {
this.terminateThread();
return;
}
continue;
}
}
}
}
catch (SocketTimeoutException e) {
e.printStackTrace();
try {
this.terminateThread();
}
catch (IOException e2) {
e2.printStackTrace();
}
}
catch (IOException e3) {
e3.printStackTrace();
try {
this.terminateThread();
}
catch (IOException e4) {
e4.printStackTrace();
}
}
}
//debug messages
void logDebugMessage(final int requiredVerbose, final String msg) {
if (Main.verboseLevel_ >= requiredVerbose) {
System.out.println("[" + this.clientIp_ + "] " + msg);
}
}
//terminate thread
void terminateThread() throws IOException {
if (!this.terminated_) {
if (this.serverIp_ != null) {
Main.servers_.remove(this.serverIp_);
}
this.clientSocket_.close();
this.in_.close();
this.out_.close();
this.logDebugMessage(3, "Cleanup successful");
this.terminated_ = true;
}
}
}
How to avoid the server from freezing if more data is being send to a client than it can handle, so that the server can continue sending data to the other clients?
Edit
So I have tried using ExecutorService, but I must be doing something completely wrong because no data is being send by the java server.
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
thread2.out_.print(msg);
thread2.out_.flush();
}
});
executorService.shutdown();
}
}
It would be great if you could show me how to implement ExecutorService the right way.
If a delay in the client processing doesn't matter, this part should be done in a distinct flow execution for each client :
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print(msg);
thread2.out_.flush();
}
For example :
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
new Thread(()-> {
thread2.out_.print(msg);
thread2.out_.flush();
})
.start();
}
}
Note that creating Threads has a cost. Using ExecutorService could be a better idea.
I'm writing something like SRM, and everything is fine until server reset. When I'm writing a sign and trying to buy it (region assigned to sign) it should send me a message that I can't, and it does, but after a server reset it doesn't, and in both cases variables are the same... This is my code:
package pl.maccraft.regs;
import java.util.logging.Logger;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import com.sk89q.worldguard.bukkit.RegionContainer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.plugin.Plugin;
public final class egs extends JavaPlugin implements Listener {
private static final Logger log = Logger.getLogger("Minecraft");
public static Economy econ = null;
#Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
getWorldGuard();
if (!setupEconomy() ) {
log.severe(String.format("[%s] - Disabled due to no Vault dependency found!", getDescription().getName()));
getServer().getPluginManager().disablePlugin(this);
return;
}
}
private WorldGuardPlugin getWorldGuard() {
Plugin plugin = getServer().getPluginManager().getPlugin("WorldGuard");
// WorldGuard may not be loaded
if (plugin == null || !(plugin instanceof WorldGuardPlugin)) {
return null; // Maybe you want throw an exception instead
}
return (WorldGuardPlugin) plugin;
}
private boolean setupEconomy() {
if (getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
}
RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
econ = rsp.getProvider();
return econ != null;
}
#EventHandler
public void playerInteract(PlayerInteractEvent event){
Player player = event.getPlayer();
if(event.getAction() == org.bukkit.event.block.Action.LEFT_CLICK_BLOCK){
Block b = event.getClickedBlock();
if (b.getType() == (Material.SIGN) || b.getType() == (Material.SIGN_POST) || b.getType() == (Material.WALL_SIGN)){
Sign sign = (Sign) b.getState();
if (sign.getLine(0).equals("[sell]")){
if (!sign.getLine(1).isEmpty()){
RegionContainer container = getWorldGuard().getRegionContainer();
RegionManager regions = container.get(player.getWorld());
if (regions != null) {
ProtectedRegion region = regions.getRegion(sign.getLine(1));
if (region != null) {
DefaultDomain owners = region.getOwners();
if(owners.contains(player.getUniqueId())){
if (!sign.getLine(2).isEmpty()){
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "say stan:" + econ.getBalance(player));
event.setCancelled(true);
player.sendMessage("To jest twój region");
sign.setLine(0, ChatColor.DARK_RED + "[sprzedam]");
sign.setLine(3, sign.getLine(1));
sign.setLine(1, player.getName());
sign.update(true);
}else{
player.sendMessage("Podaj cenę w trzeciej linii!");
}
}else{
player.sendMessage("To nie jest twój region!");
};
} else {
player.sendMessage("Taki region nie istnieje!");
}
} else {
player.sendMessage("Wystąpił błąd, który nie powinien się zdarzyć, powiadom o tym administrację!");
}
}else{
player.sendMessage("Podaj nazwę regionu w drugiej linii!");
}
}
}
}
if(event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK){
Block b = event.getClickedBlock();
if (b.getType() == (Material.SIGN) || b.getType() == (Material.SIGN_POST) || b.getType() == (Material.WALL_SIGN)){
Sign sign = (Sign) b.getState();
if (sign.getLine(0).equals(ChatColor.DARK_RED + "[sprzedam]")){
if (event.getPlayer().getName() == sign.getLine(1)){
player.sendMessage("nie możesz kupić własnej działki");
player.sendMessage(event.getPlayer().getName() + " " + sign.getLine(1));
}else{
player.sendMessage(event.getPlayer().getName() + " " + sign.getLine(1));
Double si = Double.valueOf(sign.getLine(2));
if(si <= econ.getBalance(player)){//TO POWINNO BYĆ WIĘKSZE LUB RÓWNE A NIE TAKIE SAMO!!!
RegionContainer container = getWorldGuard().getRegionContainer();
RegionManager regions = container.get(player.getWorld());
if (regions != null) {
ProtectedRegion region = regions.getRegion(sign.getLine(3));
if (region != null) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "eco take " + player.getName() + " " + si);
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "eco give " + sign.getLine(1) + " " + si);
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "rg removeowner " + sign.getLine(3) + " " + sign.getLine(1));
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "rg addowner " + sign.getLine(3) + " " + player.getName());
sign.setLine(0, ChatColor.DARK_RED + "[sprzedane]");
player.sendMessage("kupiono działkę " + sign.getLine(3) + " za " + si);
sign.setLine(1, event.getPlayer().getName());
sign.setLine(2, "");
sign.setLine(3, "");
sign.update(true);
}
}else{
player.sendMessage("wystąpił błąd");
}
}else{
player.sendMessage("Nie masz wystarczająco dużo kasy!");
}
}
}
}
}
}
}
and console returns only this:
[12:27:42] [Server thread/INFO]: [0;35;1m[Server[0;35;1m] stan:1000.0[m
[12:28:17] [Server thread/INFO]: CONSOLE issued server command: /eco take 10anat10 1000.0
[12:28:17] [Server thread/INFO]: [0;32;1m$1000 zostalo pobrane z [0;31;22m10anat10[m[0;32;1m konta. Nowy stan konta: $0[m
[12:28:17] [Server thread/INFO]: CONSOLE issued server command: /eco give 10anat10 1000.0
[12:28:17] [Server thread/INFO]: [0;32;1m$1000 zostalo dodane do konta [0;31;22m10anat10[m§. Nowy stan konta: $1000.[m
[12:28:17] [Server thread/INFO]: [0;31;1mPlease specify the world with -w world_name.[m
[12:28:17] [Server thread/INFO]: [0;31;1mPlease specify the world with -w world_name.[m
I know that I don't specify world for rg addowner and removeovner, but this isn't it and there are no more errors in the logs... Please help me.
When I change
if(event.getPlayer().getName() == sign.getLine(1)){
to
RegionContainer container = getWorldGuard().getRegionContainer();
RegionManager regions = container.get(player.getWorld());
if(regions != null){
ProtectedRegion region = regions.getRegion(sign.getLine(3));
DefaultDomain owners = region.getOwners();
if(owners.contains(player.getUniqueId())){
It acts as intended.
You need to compare strings rather then checking if the objects are equal.
string1.equals(string2)/string1.equalsIgnoreCase(string2) compares strings while string1 == string2 doesn't.
You could try this:
if (event.getPlayer().getName().equals(sign.getLine(1)))
or if you don't want it case sensitive
if (event.getPlayer().getName().equalsIgnoreCase(sign.getLine(1)))
I would like to know how to send a player a list of their shops when they type /shoplist. Also, I would like to know how to change the name of a shop depending on what they type so if they use /shopname Shop1 Pie it would change the name of Shop1 to pie. Or if they do not have a shop called shop1 then it would say a message if they don't have any shops when they make a shop then it builds a new section in the config for them.
Here is my main file:
public class Shops extends JavaPlugin implements Listener {
public void onEnable() {
Bukkit.getServer().getLogger().info("************************");
Bukkit.getServer().getLogger().info("*Shops Plugin Enabled *");
Bukkit.getServer().getLogger().info("*Shops by McMatt *");
Bukkit.getServer().getLogger().info("************************");
Bukkit.getServer().getPluginManager().registerEvents(new Signs(), this);
getConfig().options().copyDefaults(true);
saveConfig();
}
public void onDisable() {
Bukkit.getServer().getLogger().info("************************");
Bukkit.getServer().getLogger().info("*Shops Plugin Disabled *");
Bukkit.getServer().getLogger().info("*Shops by McMatt *");
Bukkit.getServer().getLogger().info("************************");
}
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
if (cmd.getName().equalsIgnoreCase("shops")) {
if (!(sender instanceof Player)) {
sender.sendMessage("You must be a player to run this command");
return true;
}
Player player = (Player) sender;
if (!player.hasPermission("shops.shops")) {
player.sendMessage(ChatColor.RED + "You do not have to permission (shops.shops)");
return true;
} else {
player.sendMessage(ChatColor.GOLD + "Shops:");
player.sendMessage(ChatColor.RED + "---" + ChatColor.GOLD + "Commands" + ChatColor.RED + "---");
player.sendMessage(ChatColor.DARK_GREEN + "/shops" + ChatColor.GREEN + " Displays this");
player.sendMessage(ChatColor.DARK_GREEN + "/shopslist" + ChatColor.GREEN + " Used to list shops");
player.sendMessage(ChatColor.RED + "---" + ChatColor.GOLD + "Signs" + "---");
player.sendMessage(ChatColor.DARK_GREEN + "First line:" + ChatColor.GREEN + " [shop]");
player.sendMessage(ChatColor.DARK_GREEN + "Second line:" + ChatColor.GREEN + " {Open or Closed}");
}
}
return true;
}
public boolean onCommand1(CommandSender sender, Command cmd, String commandLabel, String[] args) {
if (cmd.getName().equalsIgnoreCase("shopslist")) {
sender.sendMessage("Getting shops info!");
sender.sendMessage(getConfig().getString("" + sender.getName()));
return true;
}
return false;
}
}
Here's my listener file
public class Signs implements Listener {
#EventHandler
public void onSignChange(SignChangeEvent e) {
if (e.getLine(0).equalsIgnoreCase("[shop]")) {
Block attached = e.getBlock().getRelative(0, -1, 0);
String name = e.getPlayer().getDisplayName();
if (!(attached.getType() == Material.CHEST))
e.getPlayer().sendMessage(ChatColor.RED + "Please place the shop on a chest!");
else {
if (!e.getPlayer().hasPermission("shops.create"))
e.getPlayer().sendMessage(ChatColor.RED + "You don't have permission to create a shop! (shops.create)");
else {
if (!Arrays.asList("open", "closed").contains(e.getLine(1).toLowerCase())) {
e.getPlayer().sendMessage(ChatColor.RED + "You must specify if the shop is open or closed on the second line!");
} else {
boolean closed = true;
if ("open".equalsIgnoreCase(e.getLine(1))) {
closed = false;
}
String lineThree = closed ? "§cClosed" : "§aOpen";
e.setLine(3, lineThree);
e.setLine(0, "§9[Shop]");
e.setLine(1, "§b" + name + "'s");
e.setLine(2, "§bShop");
e.getPlayer().sendMessage(ChatColor.GREEN + "Shop Created!");
e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.LEVEL_UP, 10, 10);
//if(getConfig().equals(null)){
//int shopAmount = 0;
//shopAmount = shopAmount + 1;
//getConfig().createSection(name);
//getConfig().addDefault(name + ":.Shops:", "Shop" + shopAmount);
}
}
}
}
}
#EventHandler
public void onPlayerInteract(PlayerInteractEvent e) {
if (e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
Player p = e.getPlayer();
Block b = e.getClickedBlock();
Material m = b.getType();
if (!(m == Material.SIGN_POST)) {
return;
} else {
Sign sign = (Sign) e.getClickedBlock().getState();
if ((sign.getLine(0).equalsIgnoreCase("§9[Shop]"))) {
if ((sign.getLine(3).equalsIgnoreCase("§aOpen"))) {
p.sendMessage("I opened the shop!");
}
}
}
}
}
}
And here's my configuration file
McMatt:
- Shop1
You could get the List<String> of all of the player's shops by using
config.getStringList(playerName);
So, for example, if your config looked like this:
McMatt:
- "Shop1"
- "Awesome Shop"
jojodmo:
- "Jojo Shop"
using
config.getStringList("McMatt");
Would return a List<String> containing the strings Shop1 and Awesome Shop.
Also, to avoid a NullPointerException, you should make sure the player has shops in the config by using
if(config.contains(playerName))
and send the player a message telling them that they have no shops.
So, your code could look something like this:
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
if(cmd.getName().equalsIgnoreCase("shops")){
//your code
if(sender instanceof Player){
Player player = (Player) sender;
String name = player.getName();
if(config.contains(name)){
List<String> shops = config.getStringList(name);
for(String shop : shops){
//do something with the shop
}
}
else{
//the user has no shops
}
}
//...
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have Java Swing application which is designed in poor architecture.
GUI, SQL Statement ... etc, all one class.
Ex. NewEmployee.java have GUI, SQL insert,update,delete & select in this class, there is no separation.
From what I read we should separate the logic from the design.
To be honest I don't know how to do that, or how to understand it.
I need to know how to break down my project so I got : model, view & controller, but I need to know what each one mean & how each one should cooperate with other.
could you help in separating this:
public class PendingOInvoices extends CFrame {
private static final long serialVersionUID = 1L;
private JToolBar toolBar = new JToolBar();
private JPanel panel_1 = new JPanel();
private JLabel label3 = new JLabel();
private CText cSearch = new CText();
private JLabel label2 = new JLabel();
private CDCombo cSearchBy = new CDCombo();
private CBGeneral cMakeBill = new CBGeneral();
private Component component5_1 = Box.createHorizontalStrut(3);
private CBRefreshE cRefresh = new CBRefreshE();
private CBCloseE cClose = new CBCloseE();
private Component component5_3 = Box.createHorizontalStrut(3);
private JLabel label1 = new JLabel();
private CDate cTDate = new CDate();
private MyOutBillingModel model1 = new MyOutBillingModel();
private JPVTableView table1 = new JPVTableView(model1);
private JLabel label = new JLabel();
private CDate cFDate = new CDate();
private CBNewE cNew = new CBNewE();
private CBModifyE cModify = new CBModifyE();
private Component component5 = Box.createHorizontalStrut(3);
private Component component5_2 = Box.createHorizontalStrut(3);
private JLabel label4 = new JLabel();
private CDCombo cFilter = new CDCombo();
public PendingOInvoices () {
setTitle("Out Patients - Pending Encounters");
setFrameIcon("opdbilling");
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
setSize(new Dimension(980, 546));
getContentPane().setLayout(new BorderLayout());
getContentPane().add(panel_1, BorderLayout.NORTH);
panel_1.setMaximumSize(new Dimension(0, 44));
panel_1.setMinimumSize(new Dimension(0, 44));
panel_1.setLayout(null);
panel_1.setPreferredSize(new Dimension(0, 44));
panel_1.add(label3);
label3.setText("Search engine:");
label3.setBounds(790, 0, 170, 19);
panel_1.add(cSearch);
cSearch.addKeyListener(new CSearchKeyListener());
cSearch.setBounds(790, 20, 170, 23);
panel_1.add(label2);
label2.setText("Search by:");
label2.setBounds(662, 0, 127, 19);
panel_1.add(cSearchBy);
cSearchBy.addActionListener(new CSearchByActionListener());
cSearchBy.setBounds(662, 20, 127, 23);
cSearchBy.addItem("ID No");
cSearchBy.addItem("File No");
cSearchBy.addItem("Patient Name (EN)");
cSearchBy.addItem("Patient Name (ع)");
cSearchBy.addItem("Encounter No");
toolBar.setBounds(0, 0, 264, 45);
panel_1.add(toolBar);
toolBar.setFloatable(false);
toolBar.add(cRefresh);
toolBar.add(component5_1);
toolBar.add(cNew);
cNew.addActionListener(new CNewActionListener());
toolBar.add(component5_3);
toolBar.add(cModify);
cModify.addActionListener(new CModifyActionListener());
toolBar.add(component5);
toolBar.add(cMakeBill);
cMakeBill.setText("Make Bill");
cRefresh.addActionListener(new CRefreshActionListener());
cMakeBill.setIcon(SwingResourceManager.getIcon(PendingOInvoices.class, "/images/small/billmaker.png"));
cMakeBill.addActionListener(new CMakeBillActionListener());
toolBar.add(component5_2);
toolBar.add(cClose);
cClose.addActionListener(new CCloseActionListener());
panel_1.add(label1);
label1.setText("To Date:");
label1.setBounds(382, 0, 115, 19);
panel_1.add(cTDate);
cTDate.addTextListener(new CTDateTextListener());
cTDate.addKeyListener(new CTDateKeyListener());
cTDate.setBounds(382, 20, 115, 23);
getContentPane().add(table1);
table1.getJTable().addMouseListener(new table1JTableMouseListener());
table1.getJTable().addKeyListener(new Table1JTableKeyListener());
cSearch.setHorizontalAlignment(SwingConstants.CENTER);
panel_1.add(label);
label.setText("From Date:");
label.setBounds(266, 0, 115, 19);
panel_1.add(cFDate);
cFDate.setText("01/01/"+cTDate.getText().substring(7));
cFDate.addTextListener(new CFDateTextListener());
cFDate.addKeyListener(new CFDateKeyListener());
cFDate.setBounds(266, 20, 115, 23);
panel_1.add(label4);
label4.setText("Filtering Options:");
label4.setBounds(498, 0, 163, 19);
panel_1.add(cFilter);
cFilter.addActionListener(new CFilterActionListener());
cFilter.setBounds(498, 20, 163, 23);
cFilter.addItem("--- Choose ---");
cFilter.addItem("Guarantors Shares Only");
cFilter.addItem("Cash Patients Only");
cFilter.addItem("Patients Got Discount Only");
setWidths();
fillEncounters();
}
public void updateMe(String encno){
fillEncounters();
table1.getTable().requestFocus();
table1.getTable().setFocusCell(table1.search(encno, 1),1);
}
private void setWidths() {
model1.setColumnCount(9);
model1.setRowCount(0);
table1.getColumn(0).setPreferredWidth(75);
table1.getColumn(1).setPreferredWidth(90);
table1.getColumn(2).setPreferredWidth(350);
table1.getColumn(3).setPreferredWidth(80);
table1.getColumn(4).setPreferredWidth(80);
table1.getColumn(5).setPreferredWidth(80);
table1.getColumn(6).setPreferredWidth(80);
table1.getColumn(7).setPreferredWidth(80);
table1.getColumn(8).setPreferredWidth(20);
table1.getColumn(0).setHeaderValue("Date");
table1.getColumn(1).setHeaderValue("Encounter No");
table1.getColumn(2).setHeaderValue("Patient Name");
table1.getColumn(3).setHeaderValue("Total");
table1.getColumn(4).setHeaderValue("Guarantors");
table1.getColumn(5).setHeaderValue("Discount");
table1.getColumn(6).setHeaderValue("Paid");
table1.getColumn(7).setHeaderValue("Balance");
table1.getColumn(8).setHeaderValue("");
table1.setColumnType(0, JPVTable.DATE, null);
table1.setColumnType(1, JPVTable.DATE, null);
table1.setColumnType(2, JPVTable.TEXT, null);
table1.setColumnType(3, JPVTable.DOUBLE, null);
table1.setColumnType(4, JPVTable.DOUBLE, null);
table1.setColumnType(5, JPVTable.DOUBLE, null);
table1.setColumnType(6, JPVTable.DOUBLE, null);
table1.setColumnType(7, JPVTable.DOUBLE, null);
table1.setColumnType(8, JPVTable.BOOLEAN, null);
CTableConfig mc = new CTableConfig();
mc.newConfigureTable(table1,8,0,true);
table1.getTable().getColumnModel().getColumn(8).setHeaderRenderer(new CHGeneral(new MyItemListener()));
}
class MyItemListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
Object source = e.getSource();
if (!(source instanceof AbstractButton)) return;
boolean checked = e.getStateChange() == ItemEvent.SELECTED;
int rows = model1.getRowCount();
for(int x = 0; x < rows; x++){
model1.setValueAt(checked,x,8);
}
}
}
private String getSearchColumn(){
if(cSearchBy.getSelectedIndex() == 0){
return "patients.PatID";
}else if(cSearchBy.getSelectedIndex() == 1){
return "encounters.Enc_Patient";
}else if(cSearchBy.getSelectedIndex() == 2){
return "concat(patients.PatFirst,' ', patients.PatFather,' ',patients.PatMiddle,' ',patients.PatFamily)";
}else if(cSearchBy.getSelectedIndex() == 3){
return "concat(patients.PatFirstA,' ', patients.PatFatherA,' ',patients.PatMiddleA,' ',patients.PatFamilyA)";
}else if(cSearchBy.getSelectedIndex() == 4){
return "encounters.Enc_No";
}
return "";
}
private void fillEncounters(){
String currentValue = "";
int r = table1.getTable().getFocusRow();
cFDate.setFormat(2);
cTDate.setFormat(2);
String sql = "SELECT \n"
+"Date_Format(Enc_Date,'%d/%m/%Y'), \n"
+"encounters.Enc_No, \n"
+"CONCAT(' ',patients.PatFirst,' ',patients.PatFather,' ',patients.PatMiddle,' ',patients.PatFamily), \n"
+"FORMAT((Enc_Clinics+Enc_Labs+Enc_Rads+Enc_MED),2), \n"
+"FORMAT(Enc_Guarantor,2), \n"
+"FORMAT(Enc_Discount,2), \n"
+"FORMAT((Enc_Receipt-Enc_Payment),2), \n"
+"FORMAT(Enc_Balance,2), \n"
+""+Boolean.FALSE+", \n"
+"encounters.Enc_Patient, \n"
+"VERSION \n"
+"FROM \n"
+"encounters \n"
+"INNER JOIN encsummary ON encounters.Enc_No = encsummary.Enc_No \n"
+"INNER JOIN patients ON encounters.Enc_Patient = patients.PatNo \n"
+"WHERE Enc_Date Between '"+cFDate.getText()+"' AND '"+cTDate.getText()+"' AND Enc_Billed = 'false' \n"
+"AND (Enc_Clinics+Enc_Labs+Enc_Rads+Enc_MED) > 0 \n";
if(cFilter.getSelectedIndex() == 1){
sql+="and Enc_Guarantor > 0 \n";
}else if(cFilter.getSelectedIndex() == 2){
sql+="and Enc_Guarantor = 0 \n";
}else if(cFilter.getSelectedIndex() == 3){
sql+="and Enc_Discount > 0 \n";
}
if(cSearch.getText().trim().length() > 0){
sql+= "and "+getSearchColumn()+" LIKE '%"+cSearch.getText()+"%' \n";
}
sql+="Order By encounters.Enc_No DESC";
cFDate.setFormat(1);
cTDate.setFormat(1);
model1.setData(CDeclare.dataAccessor.getData(sql));
try{
currentValue = table1.getValueAt(r, 1).toString();
}catch(Exception ex){}
int i = table1.search(currentValue, 1);
table1.getTable().scrollRectToVisible(new Rectangle(table1.getTable().getCellRect(i, 1, true)));
table1.getTable().changeSelection(i, 1, false, false);
}
private class CSearchByActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
cSearchBy_actionPerformed(arg0);
}
}
private class table1JTableMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent arg0) {
table1JTable_mouseClicked(arg0);
}
}
private class CMakeBillActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cMakeBill_actionPerformed(e);
}
}
private class CSearchKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cSearch_keyReleased(e);
}
}
private class CTDateKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cTDate_keyReleased(e);
}
}
private class CRefreshActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cRefresh_actionPerformed(e);
}
}
private class CTDateTextListener implements TextListener {
public void textValueChanged(TextEvent e) {
cTDate_textValueChanged(e);
}
}
private class CCloseActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cClose_actionPerformed(e);
}
}
private class CFDateKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cFDate_keyReleased(e);
}
}
private class CFDateTextListener implements TextListener {
public void textValueChanged(TextEvent e) {
cFDate_textValueChanged(e);
}
}
private class CNewActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cNew_actionPerformed(e);
}
}
private class CModifyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cModify_actionPerformed(e);
}
}
private class Table1JTableKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
table1JTable_keyPressed(e);
}
}
private class CFilterActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cFilter_actionPerformed(e);
}
}
protected void cSearchBy_actionPerformed(ActionEvent arg0) {
if(cSearchBy.getSelectedIndex() == 3){
cSearch.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}else{
cSearch.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
}
cSearch.setText(null);
}
protected void table1JTable_mouseClicked(MouseEvent e) {
int c = table1.getTable().getSelectedColumn();
if(e.getClickCount() >= 2 && c != 8){
cModify_actionPerformed(null);
}
}
private void insertInvoice(){
double total = 0,guarantors = 0,grandtotal = 0;
CDate datg = new CDate();
String encno = "",invno = "",version = "";
for(int i = 0; i < model1.getRowCount();i++){
if(model1.getValueAt(i, 8).equals(Boolean.TRUE)){
if(datg.getFormat() != 1){
datg.setFormat(1);
}
encno = model1.getValueAt(i, 1).toString();
version = model1.getValueAt(i, 10).toString();
if(!CDeclare.SAMEVERSION("encounters","Enc_No",encno,version)){
return;
}
CDeclare.dataAccessor.UpdateDB("update encounters set VERSION = (VERSION+1) WHERE Enc_No = '"+encno+"'");
CDeclare.doubleValue.setValue(model1.getValueAt(i,3));
total = CDeclare.doubleValue.getDouble();
CDeclare.doubleValue.setValue(model1.getValueAt(i,4));
guarantors = CDeclare.doubleValue.getDouble();
grandtotal = total-guarantors;
invno = CDeclare.newNumber.getLastYearMonthNo(datg, "LastTemp");
datg.setFormat(2);
String sql = " Insert into invoice(Inv_No,Inv_Entry_Date,Inv_Kind,Inv_ClientKind,Inv_ClientSubKind,Inv_SubRefNo,Inv_Name,Inv_Date," +
"Inv_VatPercent,Inv_SubTotal,Inv_OthersTotal,Inv_Total,EMPIII) values (" +
"'" + invno + "'," +
"'" + CDeclare.getServerDateMySSQL() + "'," +
"'" + "S" + "'," +
"'" + "P" + "'," +
"'" + "OP" + "'," +
"'" + encno + "'," +
"'" + model1.getValueAt(i, 9) + "'," +
"'" + datg.getText() + "'," +
"'" + CDeclare.VAT + "'," +
"'" + total + "'," +
"'" + guarantors + "'," +
"'" + grandtotal + "'," +
"'" + CDeclare.EMPNO + "'" + ")";
CDeclare.dataAccessor.InsertDB(sql);
insertInvDetails(encno,invno);
}
}
}
private void insertInvDetails(String encno,String invno){
CCurrency vat = new CCurrency();
String invDetSql = "SELECT \n"
+"Sec_Account, \n"
+"Sec_Department, \n"
+"Ch_Kind, \n"
+"FORMAT((SUM(Ch_Total)/("+(1+CDeclare.VAT)+")),2), \n"
+"FORMAT(SUM(Ch_Total),2) \n"
+"FROM \n"
+"enccharges \n"
+"INNER JOIN medicalsections ON Ch_Section = Sec_No \n"
+"WHERE \n"
+"Ch_EncNo = '"+encno+"' \n"
+"GROUP BY Ch_Kind,Sec_Account,Sec_Department for update \n";
Vector<?> data = CDeclare.dataAccessor.getData(invDetSql);
for(int i = 0; i < data.size(); i++){
Vector<?> v = (Vector<?>) data.elementAt(i);
CDeclare.myDouble.setValue(v.elementAt(4));
CDeclare.doubleValue.setValue(v.elementAt(3));
vat.setDouble(vat.getDouble()+CDeclare.myDouble.getDouble()-CDeclare.doubleValue.getDouble());
String insSql = "Insert into invoicedetails(Inv_No,Inv_Account,Inv_Department,Inv_Kind,Inv_Total,Inv_TaxTotal) values (" +
"'" + invno + "'," +
"'" + v.elementAt(0) + "'," +
"'" + v.elementAt(1) + "'," +
"'" + v.elementAt(2) + "'," +
"'" + CDeclare.doubleValue.getDouble() + "'," +
"'" + CDeclare.myDouble.getDouble()+ "'" + ")";
CDeclare.dataAccessor.InsertDB(insSql);
}
CDeclare.dataAccessor.UpdateDB("update invoice set Inv_Vat = '"+vat.getDouble()+"' where Inv_No = '"+invno+"'");
String sqlUpdateEncounter = " Update encounters set \n" +
" Enc_Billed = 'true',\n" +
" Enc_Status = 'D',\n" +
" Enc_BillNo = '" + invno + "'\n " +
" where Enc_No = '" + encno + "'";
CDeclare.dataAccessor.UpdateDB(sqlUpdateEncounter);
}
protected void cMakeBill_actionPerformed(ActionEvent e) {
int option = (new CConfirms()).getSelection('S',"This operation will generate temporary invoices for selected encounters \n Are you sure ?!!!");
if(option != 0){
return;
}
CDeclare.dataAccessor.initAutoCommit();
CDeclare.dataAccessor.beginTransaction();
insertInvoice();
if(CDeclare.exCounter == 0){
CDeclare.dataAccessor.endTransaction();
fillEncounters();
}else{
CDeclare.dataAccessor.rollBack();
new CAlerts('D');
}
}
protected void cSearch_keyReleased(KeyEvent e) {
fillEncounters();
}
protected void cTDate_keyReleased(KeyEvent e) {
if(cTDate.getText().length() == 10){
fillEncounters();
}
}
protected void cRefresh_actionPerformed(ActionEvent e) {
fillEncounters();
}
protected void cTDate_textValueChanged(TextEvent e) {
if(cTDate.getText().length() == 10){
fillEncounters();
}
}
protected void cClose_actionPerformed(ActionEvent e) {
dispose();
}
protected void cFDate_keyReleased(KeyEvent e) {
if(cFDate.getText().length() == 10){
fillEncounters();
}
}
protected void cFDate_textValueChanged(TextEvent e) {
if(cFDate.getText().length() == 10){
fillEncounters();
}
}
protected void cNew_actionPerformed(ActionEvent e) {
NewEncounter newr = new NewEncounter(getTitle() + " - "+cNew.getText());
newr.insertMode();
newr.setOwner(this);
newr.setVisible(true);
}
protected void cModify_actionPerformed(ActionEvent e) {
int r = table1.getTable().getFocusRow();
String encno = model1.getValueAt(r,1).toString();
NewEncounter newr = new NewEncounter(getTitle() + " - "+cModify.getText());
newr.modifyMode();
newr.setOwner(this);
newr.fillEncounter(encno);
newr.setVisible(true);
}
protected void table1JTable_keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
e.consume();
cModify_actionPerformed(null);
}
}
protected void cFilter_actionPerformed(ActionEvent e) {
fillEncounters();
}
}
class MyOutBillingModel extends PVTableModel {
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int iRow, int iCol) {
try{
if(iCol == 8){
return true;
}
}catch(Exception ex){}
return false;
}
Your on the right track if you know what MVC is. You may also want to look at MVVM as it has the same goal. Let's break it down:
Model - simple classes with getter/setters and no logic or details about storage
View - classes or pages that display Model data in some organized way
Controller - the object that accepts actions from the View, manipulates Model, and transfers control to a new View (passing it a Model)
In general what we like to do is first "model" the data into classes that have no business logic, UI concepts or storage dependencies (like SQL). They are simple objects with getter/setter for data. Then the "view" classes/pages are designed so they know how to read those model objects and display them in whatever way makes sense. But the view does not know where/how those model objects are stored. The glue that puts the view and model together is the "controller", which is why it has that name. Typically the user interacts with the view to get/change data, and the view then invokes the controller with an "action" like "get-employee". The control is the only thing that knows what the action means and what to do. In the simple case, the controller will go get the data from the storage, and then decide on what the next view should be for the user. It takes the model object it loaded from storage, constructs the view, and passes the model to the view where it is rendered. The key point here is that the first view has no idea of what the controller is going to do and has no idea what the next view will be. That's all the business of the controller.
So in your case, you might have a few Employee Views like NewEmployee, EmployeeDetails, EmployeeListing. And then you might have a Model like Employee. You should be able to build these views with no SQL. That's how you know you are doing this right. Then, you introduce the Controller, like an EmployeeController. Then, you tie Button presses and click events in your Views to the action methods on the Controller. So you can add methods like this:
View listEmployees()
View createEmployee(Employee e)
View getEmployee(long id)
View deleteEmployee(long id)
Your Controller should then be the only component that interacts with storage, and then decides on what the "next" View should be. That's why it returns a View and not the Model. For instance, the method might look something like this:
public class EmployeeController {
. . .
public View listEmployees() {
List<Employee> employees = storage.getAllEmployees();
return new EmployeeListing(employees);
}
}
That's the basic concept and how the separation works. In most real MVC/MVVC frameworks, there is more sophistication around the mapping of actions and views.
Notice I also added a "storage" object so that even the Controller does not know that SQL is used. That will lead you to concepts like DAO which is how to abstract the actual storage details away from the rest of the app, if you want to.
Model View Controller (MVC) is a concept you may want to use. More about that in here: How to correctly implement swing-Please check the accepted answer in this link.
In your case, don't break the working code unless you have to...Remember that such a design change may cost more that its worth for a running system.
Start by separating all the SQL code into a separate package with interfaces and implementations. You can test those without the UI and put them aside.
Then I'd recommend making all the Swing classes another separate package. Do not call new to create and attach Listeners in the Swing classes. Instead, provide a mechanism for passing them in via constructors or setters. Inject those dependencies.
Model classes ought to represent the problem you're solving without a UI or database. See if they do.
Last have the controller package with classes that instantiate the listeners and views, gives the views the listeners they need, and fulfill the use cases by manipulating model and persistence objects.
That's MVC.
from what i read we should separate the logic from the design.
to be honest i don't know how to do that, or how to understand it.
The main reason (beyond the usual "cleaner code and architecture") why you want to do that and the principles behind can be explained best on an example.
Let's assume, you have a nice working desktop UI application. Now you want to create a web version of the very same application.
When the GUI application has placed all the business logic and all the DB accesses in the forms (or whatever the equivalent is), you got a problem. Because everything is coupled so tightly together, it is virtually impossible to re-use anything from the GUI application. So you start duplicating your code, and that's a real bad-bad. That way you end up with two code bases which have to be maintained.
In order to get the most out of the reusing game, you want to separate (at least) the UI from the underlying business logic. And while we're at it, it is also not such a bad idea to split the levels of abstraction once more and extracting the data model.
Now we can do something like this:
+-----------+
| Web UI |<<------+
+-----------+ |
| +-----------+ +------------+
+----->>| Biz Logic |<<---->>| Data Model |
| +-----------+ +------------+
+-----------+ |
| GUI |<<------+
+-----------+
To achieve that, you have to do certain things:
split the code accordingly to have independent (code) modules
remove all dependencies from right hand parts to left hand parts (ie. logic should not know anything about the UI details)
Methodical frameworks like MVC or MVVM or others can be considered as best-practice toolbelts to support you doing that at the interface between the logic and the UI parts. These concepts are proven and have matured over a long time. Strictly speaking, it is not required that you follow these concepts, but it is strongly recommended, as they not only help with architectural decisions but also and the make day-to-day coding work much easier, because of the existing framework implementations (again, that varies on what language etc. is used).