Merge branch 'development' of https://github.com/PTE-SH/ShadowHunterGame into development
This commit is contained in:
commit
1a2b50ffb2
23
src/carte/CarteEquipementEffet.java
Normal file
23
src/carte/CarteEquipementEffet.java
Normal file
@ -0,0 +1,23 @@
|
||||
package carte;
|
||||
|
||||
import main.Joueur;
|
||||
import main.Type;
|
||||
|
||||
public class CarteEquipementEffet<T extends Type> extends CarteEquipement<Type> {
|
||||
|
||||
public CarteEquipementEffet(String nom, String description) {
|
||||
super(nom, description);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7036514419711836673L;
|
||||
|
||||
@Override
|
||||
public void reverse(Joueur j) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
24
src/ihm/controller/ChoisirEquipement.java
Normal file
24
src/ihm/controller/ChoisirEquipement.java
Normal file
@ -0,0 +1,24 @@
|
||||
package ihm.controller;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import carte.CarteEquipement;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import main.Joueur;
|
||||
|
||||
public class ChoisirEquipement implements Initializable{
|
||||
@FXML private GridPane equipement;
|
||||
|
||||
private Joueur joueurVole;
|
||||
private CarteEquipement equipementVole;
|
||||
|
||||
@Override
|
||||
public void initialize(URL arg0, ResourceBundle arg1) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package ihm.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import carte.CarteLieu;
|
||||
import ihm.SpriteAnimation;
|
||||
import javafx.animation.Animation;
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.util.Duration;
|
||||
import main.Joueur;
|
||||
|
||||
public class JouerSonTour1Controller implements Initializable{
|
||||
@FXML private Pane rootPane;
|
||||
@FXML private Label d6;
|
||||
@FXML private Label d4;
|
||||
@FXML private Button btnStop;
|
||||
@FXML private Button btnLancer;
|
||||
|
||||
@Override
|
||||
public void initialize(URL arg0, ResourceBundle arg1) {
|
||||
btnStop.setVisible(false);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void lancerDes(MouseEvent mouseEvent)throws InterruptedException{
|
||||
System.out.println("\tLancements des dès");
|
||||
|
||||
btnLancer.setVisible(false);
|
||||
btnStop.setVisible(true);
|
||||
|
||||
/*for (int i=1; i<7; i++) {
|
||||
Thread.sleep(500);
|
||||
d6.setText(Integer.toString(i));
|
||||
}
|
||||
|
||||
for (int i=1; i<5; i++) {
|
||||
Thread.sleep(500);
|
||||
d4.setText(Integer.toString(i));
|
||||
}*/
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void stop(MouseEvent mouseEvent) throws IOException, InterruptedException {
|
||||
Thread.sleep(2000);
|
||||
final URL fxmlURL = getClass().getResource("/ihm/ressources/Jouer_tour(2)carte_lieux.fxml");
|
||||
final ResourceBundle bundle = ResourceBundle.getBundle("domaine.properties.langue", Locale.ENGLISH);
|
||||
final FXMLLoader fxmlLoader = new FXMLLoader(fxmlURL, bundle);
|
||||
Pane root = fxmlLoader.load();
|
||||
rootPane.getChildren().setAll(root);
|
||||
}
|
||||
}
|
20
src/ihm/controller/JouerSonTour4Controller.java
Normal file
20
src/ihm/controller/JouerSonTour4Controller.java
Normal file
@ -0,0 +1,20 @@
|
||||
package ihm.controller;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import main.Joueur;
|
||||
|
||||
public class JouerSonTour4Controller extends LancerDes{
|
||||
@FXML private Label defenseur;
|
||||
|
||||
private Joueur j;
|
||||
|
||||
@Override
|
||||
public void initialize(URL arg0, ResourceBundle arg1) {
|
||||
super.initialize(arg0, arg1);
|
||||
defenseur.setText(j.getNom());
|
||||
}
|
||||
}
|
49
src/ihm/controller/LancerDes.java
Normal file
49
src/ihm/controller/LancerDes.java
Normal file
@ -0,0 +1,49 @@
|
||||
package ihm.controller;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
public class LancerDes implements Initializable{
|
||||
@FXML private Label d6;
|
||||
@FXML private Label d4;
|
||||
@FXML private Button btnStop;
|
||||
@FXML private Button btnLancer;
|
||||
|
||||
private int resultatD6;
|
||||
private int resultatD4;
|
||||
|
||||
@Override
|
||||
public void initialize(URL arg0, ResourceBundle arg1) {
|
||||
// TODO Auto-generated method stub
|
||||
btnStop.setVisible(false);
|
||||
|
||||
btnLancer.setOnAction(e -> {
|
||||
lancement();
|
||||
btnLancer.setVisible(false);
|
||||
btnStop.setVisible(true);
|
||||
});
|
||||
|
||||
btnStop.setOnAction(e -> {
|
||||
//à remplir avec les valeurs donné par le gestionnaire de jeux
|
||||
d6.setText(Integer.toString(resultatD6));
|
||||
d4.setText(Integer.toString(resultatD4));
|
||||
});
|
||||
}
|
||||
|
||||
public void lancement() {
|
||||
/*for (int i=1; i<7; i++) {
|
||||
Thread.sleep(500);
|
||||
d6.setText(Integer.toString(i));
|
||||
}
|
||||
|
||||
for (int i=1; i<5; i++) {
|
||||
Thread.sleep(500);
|
||||
d4.setText(Integer.toString(i));
|
||||
}*/
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@
|
||||
<?import javafx.scene.shape.Rectangle?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<Pane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" stylesheets="@style/popUp.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ihm.controller.JouerSonTour1Controller">
|
||||
<Pane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" stylesheets="@style/popUp.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ihm.controller.LancerDes">
|
||||
<children>
|
||||
<Button fx:id="btnLancer" layoutX="70.0" layoutY="140.0" mnemonicParsing="false" onMouseClicked="#lancerDes" text="%lancer.de.des">
|
||||
<Button fx:id="btnLancer" layoutX="70.0" layoutY="140.0" mnemonicParsing="false" text="%lancer.de.des">
|
||||
<font>
|
||||
<Font size="14.0" />
|
||||
</font></Button>
|
||||
@ -35,7 +35,7 @@
|
||||
<Font size="48.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Button fx:id="btnStop" layoutX="101.0" layoutY="140.0" mnemonicParsing="false" onMouseClicked="#stop" text="Stop">
|
||||
<Button fx:id="btnStop" layoutX="101.0" layoutY="140.0" mnemonicParsing="false" text="Stop">
|
||||
<font>
|
||||
<Font size="14.0" />
|
||||
</font>
|
||||
|
@ -1,16 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ScrollPane?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
|
||||
|
||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ihm.controller.ChoisirEquipement">
|
||||
<children>
|
||||
<Pane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" stylesheets="@style/popUp.css">
|
||||
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" stylesheets="@style/popUp.css">
|
||||
<children>
|
||||
<Label layoutX="58.0" layoutY="62.0" text="%voler.equipement.joueur" />
|
||||
<Label layoutX="53.0" layoutY="90.0" text="%choisir.equipement.a.voler" />
|
||||
<Label layoutX="58.0" layoutY="14.0" text="%voler.equipement.joueur" />
|
||||
<ScrollPane layoutX="28.0" layoutY="40.0" prefHeight="128.0" prefWidth="200.0">
|
||||
<content>
|
||||
<GridPane fx:id="equipement">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<ImageView fitHeight="60.0" fitWidth="43.0" pickOnBounds="true" preserveRatio="true" />
|
||||
<ImageView fitHeight="60.0" fitWidth="43.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="1" />
|
||||
<ImageView fitHeight="60.0" fitWidth="43.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="2" />
|
||||
<ImageView fitHeight="60.0" fitWidth="43.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="3" />
|
||||
</children>
|
||||
</GridPane>
|
||||
</content>
|
||||
</ScrollPane>
|
||||
</children>
|
||||
</Pane>
|
||||
</children>
|
||||
|
@ -4,18 +4,30 @@
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.shape.Polygon?>
|
||||
<?import javafx.scene.shape.Rectangle?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
|
||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ihm.controller.JouerSonTour4Controller">
|
||||
<children>
|
||||
<Pane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" stylesheets="@style/popUp.css">
|
||||
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="180.0" prefWidth="255.0" stylesheets="@style/popUp.css">
|
||||
<children>
|
||||
<Label layoutX="107.0" layoutY="23.0" text="attaque" />
|
||||
<Button layoutX="78.0" layoutY="144.0" mnemonicParsing="false" text="%lancer.de.des" />
|
||||
<Label layoutX="161.0" layoutY="23.0" text="%joueur2" />
|
||||
<Label layoutX="46.0" layoutY="23.0" text="%joueur3" />
|
||||
<Pane layoutX="40.0" layoutY="49.0" prefHeight="85.0" prefWidth="85.0" stylesheets="@style/plateau.css" />
|
||||
<Pane layoutX="144.0" layoutY="49.0" prefHeight="85.0" prefWidth="85.0" />
|
||||
<Label layoutX="32.0" layoutY="6.0" text="Vous attaquez" />
|
||||
<Button fx:id="btnLancer" layoutX="78.0" layoutY="144.0" mnemonicParsing="false" text="%lancer.de.des" />
|
||||
<Label fx:id="defenseur" layoutX="151.0" layoutY="6.0" text="%joueur2" />
|
||||
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="WHITE" height="87.0" layoutX="26.0" layoutY="45.0" stroke="BLACK" strokeType="INSIDE" width="86.0" />
|
||||
<Polygon fill="WHITE" layoutX="177.0" layoutY="92.0" points="-50.0, 40.0, 50.0, 40.0, 0.0, -60.0" stroke="BLACK" strokeType="INSIDE" />
|
||||
<Label fx:id="d6" layoutX="56.0" layoutY="55.0" styleClass="des" text="6">
|
||||
<font>
|
||||
<Font size="48.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="d4" layoutX="163.0" layoutY="55.0" styleClass="des" text="4">
|
||||
<font>
|
||||
<Font size="48.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Button fx:id="btnStop" layoutX="105.0" layoutY="144.0" mnemonicParsing="false" text="Stop" />
|
||||
</children>
|
||||
</Pane>
|
||||
</children>
|
||||
|
@ -70,6 +70,20 @@ public class Joueur {
|
||||
updateVie();
|
||||
}
|
||||
|
||||
//pour tests IA
|
||||
public void setHP(int val) {
|
||||
this.stats.put("HP", val);
|
||||
}
|
||||
|
||||
//pour tests IA
|
||||
public void setNbEquip(int val) {
|
||||
this.stats.put("nb_equipements", val);
|
||||
}
|
||||
//pour tests IA
|
||||
public void setDamage(int val) {
|
||||
this.stats.put("DAMAGE", val);
|
||||
}
|
||||
|
||||
private void updateVie() {
|
||||
int damage = damageTaken();
|
||||
this.plateau.updateVieJoueur(this, damage);
|
||||
|
@ -10,10 +10,10 @@ import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import carte.CarteEquipement;
|
||||
import carte.CarteEquipementEffet;
|
||||
import carte.CarteEquipementStat;
|
||||
import personnage.Allie;
|
||||
import personnage.CartePersonnage.Equipe;
|
||||
import personnage.Franklin;
|
||||
import personnage.LoupGarou;
|
||||
import personnage.Vampire;
|
||||
|
||||
public class IATest {
|
||||
@ -87,14 +87,14 @@ public class IATest {
|
||||
j2.setCartePersonnage(new Vampire(j2));
|
||||
|
||||
//test 1 : joueur ami, on ne se devoile pas
|
||||
jIA.setStat("HP", 10);
|
||||
jIA.setHP(10);
|
||||
assertFalse(cIA.devoilerIAVampire(jIA, j2));
|
||||
|
||||
//test 2 : joueur ennemi et peu de HP, on se devoile
|
||||
assertTrue(cIA.devoilerIAVampire(jIA, j1));
|
||||
|
||||
//test 3 : joueur ennemi et beaucoup de HP, on se devoile pas
|
||||
jIA.setStat("HP", 12);
|
||||
jIA.setHP(12);
|
||||
assertFalse(cIA.devoilerIAVampire(jIA, j1));
|
||||
|
||||
}
|
||||
@ -107,16 +107,15 @@ public class IATest {
|
||||
jIA.setCartePersonnage(new Franklin(jIA));
|
||||
j1.setCartePersonnage(new Franklin(j1));
|
||||
j2.setCartePersonnage(new Vampire(j2));
|
||||
|
||||
joueurs.add(j1);
|
||||
joueurs.add(j2);
|
||||
|
||||
//test 1 : ennemi avec moins de 4 hp, on se devoile
|
||||
j2.setStat("HP", 4);
|
||||
j2.setHP(4);
|
||||
assertTrue(cIA.devoilerIAGeorges(jIA, joueurs));
|
||||
|
||||
//test 2 : pas d'ennemi avec moins de 4 hp, on se devoile pas
|
||||
j2.setStat("HP", 6);
|
||||
j2.setHP(6);
|
||||
assertFalse(cIA.devoilerIAGeorges(jIA, joueurs));
|
||||
|
||||
}
|
||||
@ -132,11 +131,11 @@ public class IATest {
|
||||
joueurs.add(j2);
|
||||
|
||||
//test 1 : ennemi avec moins de 6 hp, on se devoile
|
||||
j2.setStat("HP", 6);
|
||||
j2.setHP(6);
|
||||
assertTrue(cIA.devoilerIAFranklin(jIA, joueurs));
|
||||
|
||||
//test 2 : pas d'ennemi avec moins de 6 hp, on se devoile pas
|
||||
j2.setStat("HP", 8);
|
||||
j2.setHP(8);
|
||||
assertFalse(cIA.devoilerIAFranklin(jIA, joueurs));
|
||||
|
||||
}
|
||||
@ -147,11 +146,11 @@ public class IATest {
|
||||
cIA.setSeed(59);
|
||||
|
||||
//test 1 : pas beaucoup de hp, on se devoile
|
||||
jIA.setStat("HP", 5);
|
||||
jIA.setHP(5);
|
||||
assertTrue(cIA.devoilerIAAllie(jIA));
|
||||
|
||||
//test 2 : beaucoup de hp, on se devoile pas
|
||||
jIA.setStat("HP", 6);
|
||||
jIA.setHP(6);
|
||||
assertFalse(cIA.devoilerIAAllie(jIA));
|
||||
|
||||
}
|
||||
@ -160,20 +159,20 @@ public class IATest {
|
||||
public void devoilerCharlesTest() {
|
||||
//setup
|
||||
cIA.setSeed(84);
|
||||
j2.setStat("HP", 4);
|
||||
j2.setHP(4);
|
||||
|
||||
//test 1 : ennemi affaibli, on se devoile
|
||||
jIA.setStat("HP", 10);
|
||||
jIA.setStat("DAMAGE", 4);
|
||||
jIA.setHP(10);
|
||||
jIA.setDamage(4);
|
||||
assertTrue(cIA.devoilerIACharles(jIA, j2));
|
||||
|
||||
//test 2 : ennemi affaibli mais pas assez de dmg pour le tuer, on se devoile pas
|
||||
jIA.setStat("DAMAGE", 3);
|
||||
jIA.setDamage(3);
|
||||
assertFalse(cIA.devoilerIACharles(jIA, j2));
|
||||
|
||||
//test 3 : charles n'a pas beaucoup de hp, on se devoile pas
|
||||
jIA.setStat("DAMAGE", 4);
|
||||
jIA.setStat("HP", 1);
|
||||
jIA.setDamage(4);
|
||||
jIA.setHP(1);
|
||||
assertFalse(cIA.devoilerIACharles(jIA, j2));
|
||||
}
|
||||
|
||||
@ -202,9 +201,9 @@ public class IATest {
|
||||
joueurs.add(j3);
|
||||
joueurs.add(j2);
|
||||
joueurs.add(j1);
|
||||
j1.setStat("HP", 4);
|
||||
j2.setStat("HP", 5);
|
||||
j3.setStat("HP", 3);
|
||||
j1.setHP(4);
|
||||
j2.setHP(5);
|
||||
j3.setHP(3);
|
||||
assertEquals(jIA.choisirJoueur(joueurs,Contexte.ATTAQUER).getStat("HP"),4);
|
||||
}
|
||||
|
||||
@ -215,11 +214,10 @@ public class IATest {
|
||||
j1.setCartePersonnage(new Franklin(j1));
|
||||
j2.setCartePersonnage(new Allie(j2));
|
||||
j3.setCartePersonnage(new Vampire(j3));
|
||||
j1.setStat("nb_equipements", 1);
|
||||
j2.setStat("nb_equipements", 2);
|
||||
j3.setStat("nb_equipements", 4);
|
||||
jIA.setStat("nb_equipements", 3);
|
||||
|
||||
j1.setNbEquip(1);
|
||||
j2.setNbEquip(2);
|
||||
j3.setNbEquip(4);
|
||||
jIA.setNbEquip(3);
|
||||
|
||||
//test 1 : on renvoit un joueur pas du meme camp avec le plus d'equipements
|
||||
joueurs.add(j3);
|
||||
@ -239,7 +237,12 @@ public class IATest {
|
||||
public void choixEquipementTest() {
|
||||
//setup
|
||||
List<CarteEquipement> equips = new ArrayList<>();
|
||||
//TODO : pas possible d'instancier des Equipements apart des EquipementStat
|
||||
equips.add(new CarteEquipementEffet("lol","mdr"));
|
||||
equips.add(new CarteEquipementEffet("lol1","mdr1"));
|
||||
equips.add(new CarteEquipementStat("lol2","mdr2"));
|
||||
|
||||
//on choisit l'equipement avec les stat en priorite
|
||||
assertTrue(jIA.choisirEquipement(equips) instanceof CarteEquipementStat);
|
||||
}
|
||||
|
||||
//TODO : devoilement emi et devoilement bob
|
||||
|
Loading…
x
Reference in New Issue
Block a user