Prechádzať zdrojové kódy

1.添加偷菜功能相关,添加redis等操作

slambb 4 rokov pred
rodič
commit
150f6d71bf
43 zmenil súbory, kde vykonal 1653 pridanie a 56 odobranie
  1. 6 0
      pom.xml
  2. 8 0
      src/main/java/com/td/boss/config/enums/ResultEnum.java
  3. 2 0
      src/main/java/com/td/boss/game/comfruit/vo/ComFruitAmountVo.java
  4. 421 31
      src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java
  5. 2 0
      src/main/java/com/td/boss/game/complayergoods/pojo/ComPlayerGoods.java
  6. 2 0
      src/main/java/com/td/boss/game/complayergoods/vo/ComPlayerGoodsVo.java
  7. 115 4
      src/main/java/com/td/boss/game/complayerland/controller/ComPlayerLandController.java
  8. 2 0
      src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLand.java
  9. 54 0
      src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLandAndCanSteal.java
  10. 25 4
      src/main/java/com/td/boss/game/complayerland/repository/ComPlayerLandRepository.java
  11. 15 1
      src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandService.java
  12. 66 3
      src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandServiceImpl.java
  13. 2 0
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandAndPlantVo.java
  14. 33 0
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandAndUserInfoVo.java
  15. 2 0
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandVo.java
  16. 8 0
      src/main/java/com/td/boss/game/complayerlog/pojo/ComPlayerLog.java
  17. 8 0
      src/main/java/com/td/boss/game/complayerlog/vo/ComPlayerLogVo.java
  18. 15 0
      src/main/java/com/td/boss/game/complayerprofit/controller/ComPlayerProfitController.java
  19. 47 0
      src/main/java/com/td/boss/game/complayerprofit/pojo/ComPlayerProfit.java
  20. 29 0
      src/main/java/com/td/boss/game/complayerprofit/repository/ComPlayerProfitRepository.java
  21. 26 0
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitService.java
  22. 42 0
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java
  23. 43 0
      src/main/java/com/td/boss/game/complayerprofit/vo/ComPlayerProfitVo.java
  24. 66 0
      src/main/java/com/td/boss/game/complayersattri/controller/ComPlayersAttriController.java
  25. 29 0
      src/main/java/com/td/boss/game/complayersattri/pojo/ComPlayersAttri.java
  26. 15 0
      src/main/java/com/td/boss/game/complayersattri/repository/ComPlayersAttriRepository.java
  27. 9 0
      src/main/java/com/td/boss/game/complayersattri/service/ComPlayersAttriService.java
  28. 30 0
      src/main/java/com/td/boss/game/complayersattri/service/ComPlayersAttriServiceImpl.java
  29. 26 0
      src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersAttriSimpleVo.java
  30. 25 0
      src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersAttriVo.java
  31. 34 0
      src/main/java/com/td/boss/game/comsetting/controller/ComSettingController.java
  32. 37 0
      src/main/java/com/td/boss/game/comsetting/pojo/ComSetting.java
  33. 9 0
      src/main/java/com/td/boss/game/comsetting/repository/ComSettingRepository.java
  34. 8 0
      src/main/java/com/td/boss/game/comsetting/service/ComSettingService.java
  35. 21 0
      src/main/java/com/td/boss/game/comsetting/service/ComSettingServiceImpl.java
  36. 34 0
      src/main/java/com/td/boss/game/comsetting/vo/ComSettingSimpleVo.java
  37. 33 0
      src/main/java/com/td/boss/game/comsetting/vo/ComSettingVo.java
  38. 68 7
      src/main/java/com/td/boss/game/comusers/controller/ComUsersController.java
  39. 6 6
      src/main/java/com/td/boss/util/CodeDOM.java
  40. 10 0
      src/main/java/com/td/boss/util/DateUtil.java
  41. 123 0
      src/main/java/com/td/boss/util/DoubleUtil.java
  42. 61 0
      src/main/java/com/td/boss/util/RedisLock.java
  43. 36 0
      src/main/resources/application.yml

+ 6 - 0
pom.xml

@@ -130,6 +130,12 @@
             <version>3.9</version>
         </dependency>
 
+        <!--redis 处理分布式锁等相关问题-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 8 - 0
src/main/java/com/td/boss/config/enums/ResultEnum.java

@@ -17,6 +17,8 @@ public enum ResultEnum {
     TOKEN_OUT_OF_DATE(303,"用户授权认证没有通过!TOKEN过期,重新获取"),
     TOKEN_DOES_NOT_HAVE_USER_ID(304,"用户授权认证没有通过!TOKEN不存在用户id"),
     NO_PARAMETERS_CARRIED(305,"输入对应参数"),
+    //setting部分
+    SETTING_IS_NULL(306,"配置信息不存在"),
     //用户数据
     USER_DOES_NOT_EXIST(400,"不能存在用户信息!"),
     USER_ENERGY_IS_INSUFFICIENT(401,"用户能量不足!"),
@@ -39,6 +41,7 @@ public enum ResultEnum {
 
     PLAYER_GOODS_SEEDS_AMOUNT_ERROR(517,"土地消耗种子数量不足"),
 
+    PLAYER_ATTRIBUTE_STRENGTH_IS_NOT(518,"用户体力不足"),
     //钱包数据
     WALLET_CNT_PLAY_ERROR(601,"钱包CNT支付参数数据错误!"),
     WALLET_SNB_INSUFFICIENT_QUANTITY(602,"snb不足以支付!"),
@@ -52,6 +55,11 @@ public enum ResultEnum {
     LAND_IS_PLANT(704,"土地已种植!"),
     LAND_NOT_PLANT(705,"土地未种植!"),
     LAND_LEASE_EXPIRED(706,"土地租赁已过期!"),
+    LAND_HARVEST_STOLEN(707,"土地收成已偷了!"),
+    LAND_STEAL_ALL(708,"土地已被偷取完!"),
+    LAND_STEAL_LOCK(709,"当前偷取人数过多,稍后再试!"),
+    LAND_PLANT_FLAG_IS_NULL(710,"土地标识为空,不能偷取"),
+    LAND_CAN_STEAL_IS_ZERO(711,"没有可收取果实的土地!"),
     //种子数据不能存在
     SEED_DATA_ERROR(801,"种子数据不存在!"),
     FRUIT_DATA_ERROR(802,"果实数据不存在!"),

+ 2 - 0
src/main/java/com/td/boss/game/comfruit/vo/ComFruitAmountVo.java

@@ -21,6 +21,8 @@ public class ComFruitAmountVo implements Serializable {
 
     private Integer amount;//这里添加一个数量,但是数据库是没有的,以背包为主
 
+    private Double amountPart;//用户收取其他的部分数据
+
     private Date createTime;//
 
     private Date updateTime;//

+ 421 - 31
src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java

@@ -21,18 +21,29 @@ import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
 import com.td.boss.game.complayerlog.pojo.ComPlayerLog;
 import com.td.boss.game.complayerlog.service.ComPlayerLogService;
 import com.td.boss.game.complayerlog.vo.ComPlayerLogVo;
+import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
+import com.td.boss.game.complayerprofit.service.ComPlayerProfitService;
+import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
+import com.td.boss.game.complayers.vo.ComPlayersVo;
+import com.td.boss.game.complayersattri.service.ComPlayersAttriService;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriSimpleVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
+import com.td.boss.game.comsetting.pojo.ComSetting;
+import com.td.boss.game.comsetting.service.ComSettingService;
+import com.td.boss.game.comsetting.vo.ComSettingVo;
 import com.td.boss.game.comsnbtran.pojo.ComSnbTran;
 import com.td.boss.game.comsnbtran.service.ComSnbTranService;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comusers.service.ComUsersService;
 import com.td.boss.game.comusers.vo.ComUsersVo;
-import com.td.boss.util.CopyUtil;
-import com.td.boss.util.DateUtil;
+import com.td.boss.util.*;
 import net.bytebuddy.asm.Advice;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -49,9 +60,15 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
     @Autowired
     private ComPlayerLandService comPlayerLandService;
 
+    @Autowired
+    private ComPlayerProfitService comPlayerProfitService;
+
     @Autowired
     private ComUsersService comUsersService;
 
+    @Autowired
+    private ComPlayersAttriService comPlayersAttriService;
+
     //交易表service
     @Autowired
     private ComSnbTranService comSnbTranService;
@@ -63,8 +80,16 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
     @Autowired
     private ComExplainLandService comExplainLandService;
 
+    //配置信息
+    @Autowired
+    private ComSettingService comSettingService;
 
 
+    private static final int TIMEOUT = 10 * 1000; //超时时间 10s
+
+    @Autowired
+    private RedisLock redisLock;
+
     /**
      * 获取仓库 全部数据,目前使用goods_type区分种子和果实
      *
@@ -90,6 +115,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 ComFruitVo comFruitVo = comFruitService.findById(e.getGoodsIndex());
                 ComFruitAmountVo comFruitAmountVo = CopyUtil.copy(comFruitVo, ComFruitAmountVo.class);
                 comFruitAmountVo.setAmount(e.getAmount());
+                comFruitAmountVo.setAmountPart(e.getAmountPart());
                 fruitList.add(comFruitAmountVo);
             }
             return e;
@@ -168,12 +194,11 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         //todo 判断土地租赁是否到期,是到期不给种植
         //租赁的剩余天数 。
         Long leaseDaysMill = comPlayerLand.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
-        if(leaseDaysMill <= 0){
-            //todo 清除记录的数据
-            //todo 清除记录的数据
-            //    1.土地租赁到期,删除土地租赁数据
+        if (leaseDaysMill <= 0) {
+            // 清除记录的数据
+            // 1.土地租赁到期,删除土地租赁数据
             comPlayerLandService.delete(comPlayerLand.getId());
-            //todo 2.把删除的这个土地的数据记录到com_explain_land中去
+            // 2.把删除的这个土地的数据记录到com_explain_land中去
             ComExplainLandVo comExplainLandVo = new ComExplainLandVo();
             comExplainLandVo = CopyUtil.copy(comPlayerLand, ComExplainLandVo.class);
             comExplainLandVo.setLandId(comPlayerLand.getConfigLandId());
@@ -202,7 +227,28 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             //如果当前时间减去种子的成熟期,还是小于种植日期,则判断未成熟
             return Result.of(null, false, ResultEnum.SEED_DATE_ERROR.getMessage(), ResultEnum.SEED_DATE_ERROR.getCode());
         }
+        //获取数据库相关配置
+        ComSettingVo comSettingVo = comSettingService.get("1").getData();
+        if (comSettingVo.equals(null)) {
+            return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
+        }
+
+        //需要redis 加锁
+        long time = System.currentTimeMillis() + TIMEOUT;
+        //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
+        String _redisKey = comPlayerLand.getPlantFlag();
+        if (!StringUtils.hasText(_redisKey)) {
+            //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
+            _redisKey = comPlayerLand.getUserId() + "or" + comPlayerLand.getConfigLandId();
+        }
+        //todo 总共偷去的数量
+        Double _stealProfits = 0d;
         try {
+            // 如果存在plantFlag 说明是新种植的
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.LAND_STEAL_LOCK.getMessage(), ResultEnum.LAND_STEAL_LOCK.getCode());
+            }
+
             //设置一个未种植状态即可
             comPlayerLand.setIsPlant(0);
             ComPlayerLandVo comPlayerLandVo = CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class);
@@ -210,6 +256,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 
             //计算一个收获量, 租赁倍数* 租赁日期下的产量
             Integer _amount = 0;
+            Double _amountPart = 0d;
             if (comPlayerLand.getLeaseDate().equals(1)) {
                 _amount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
             } else if (comPlayerLand.getLeaseDate().equals(2)) {
@@ -217,13 +264,37 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             } else if (comPlayerLand.getLeaseDate().equals(3)) {
                 _amount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
             }
+            //todo 收获果实时候,需要减去一个被偷取的利润,然后判断一个是否大于设置的利润,超出了报异常,并且收取的数量不能为小于0
+            //     拿出计算利润,收获量减去种子的成本(snb)后的百分之20 ,后面需要后台可调整
+            Integer _profit = _amount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
+            // 配置的参数。这里先直接定义
+            Double profitConfig = comSettingVo.getProfit(), stealRatioMaxConfig = comSettingVo.getStealMaxRatio(), stealRatioMinConfig = comSettingVo.getStealMinRatio(), finallyGetRatioConfig = comSettingVo.getFinalRatio();
+
+            Double _profitDouble = _profit.doubleValue();
+            Double _residualProfit = DoubleUtil.mul(_profitDouble, DoubleUtil.sub(1d, profitConfig));//如果 profitConfig 0.2,剩余利润就是0.8;
+            Double _stealAmount = DoubleUtil.sub(_profitDouble, _residualProfit); //可偷取的利润
+
+            //todo 计算总共损失的数量
+            List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(userId, comPlayerLand.getPlantFlag(), comPlayerLand.getConfigLandId());
+            for (int i = 0; i < comPlayerProfits.size(); i++) {
+                ComPlayerProfit temp = comPlayerProfits.get(i);
+                _stealProfits = DoubleUtil.add(_stealProfits, temp.getStolen());
+            }
+            Double _userHarvestPart = DoubleUtil.sub(_stealAmount, _stealProfits);
+            if (_userHarvestPart < 0.0) {
+                //差值不能为负数
+                _userHarvestPart = 0d;
+            }
+            //todo 利润
+            _amount -= _profit;
+            //用户收取的对应数量,固定收入+被偷取后剩余的部分
+            _amountPart = DoubleUtil.add(_residualProfit, _userHarvestPart);
             //果实 Type =1
-            //todo 收获果实时候
             ComPlayerGoods comPlayerGoodsSimpleVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
-
             Integer _beforeAmount = 0;
+            Double _beforeProfitPart = 0d, _afterProfitPart = 0d;
             if (comPlayerGoodsSimpleVo == null) {
-                //背包增加一个果实
+                //背包增加果实
                 comPlayerGoodsSimpleVo = new ComPlayerGoods();
                 comPlayerGoodsSimpleVo.setUserId(userId);
                 comPlayerGoodsSimpleVo.setGoodsIndex(comMallSeedVo.getHarvestId());
@@ -232,12 +303,20 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 //用种子的picture
                 comPlayerGoodsSimpleVo.setPictureName(comMallSeedVo.getPicture());
                 comPlayerGoodsSimpleVo.setAmount(_amount);
+                comPlayerGoodsSimpleVo.setAmountPart(_amountPart);
 
                 _beforeAmount = 0;
+                _beforeProfitPart = 0d;
+                _afterProfitPart = comPlayerGoodsSimpleVo.getAmountPart();
             } else {
                 _beforeAmount = comPlayerGoodsSimpleVo.getAmount();
+                _beforeProfitPart = comPlayerGoodsSimpleVo.getAmountPart();
 
                 comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() + _amount);
+                //用户利润部分
+                comPlayerGoodsSimpleVo.setAmountPart(DoubleUtil.add(comPlayerGoodsSimpleVo.getAmountPart(), _amountPart));
+
+                _afterProfitPart = comPlayerGoodsSimpleVo.getAmountPart();
             }
 
             ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
@@ -253,15 +332,230 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             _playerLog.setBeforeAmount(_beforeAmount);
             ////交易后的数据
             _playerLog.setAfterAmount(comPlayerGoodsSimpleVo.getAmount());
+            //收取时候信息记录
+            _playerLog.setTPart(_amountPart);
+            _playerLog.setTLoss(_stealProfits); //损失的部分
+            _playerLog.setBeforePart(_beforeProfitPart);
+            _playerLog.setAfterPart(_afterProfitPart);
             _playerLog.setLMultiple(comPlayerLand.getLeaseMultiple());
             ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
             comPlayerLogService.save(_playerLogVo);
+
+            //对应的,存在plantFlag则解锁
+            redisLock.unlock(_redisKey, String.valueOf(time));
         } catch (Exception e) {
+            //对应的,存在plantFlag则解锁
+            redisLock.unlock(_redisKey, String.valueOf(time));
             throw new RuntimeException(e.getMessage());
         }
 
         Map map = new HashMap();
         map.put("msg", "成功收取果实!");
+        //todo 返回一个被偷的数量
+        map.put("lossAmount",_stealProfits);
+        return Result.of(map);
+    }
+
+
+    /**
+     * 处理一键收取水果果实时候,传入对方用户id 即可
+     * <p>
+     * <p>
+     * 收获时候,操作用户snb时候,需要加锁,防止用户收取时候遗漏计算snb
+     *
+     * @param otherUserId
+     * @return
+     */
+    @PostMapping("stealAllFruit")
+    @ResponseBody
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Map> stealAllFruitFunction(
+            @RequestParam(value = "userId") String userId,
+            @RequestParam(value = "otherUserId") String otherUserId) {
+
+        Map map = new HashMap();
+
+        //获取数据库相关配置
+        ComSettingVo comSettingVo = comSettingService.get("1").getData();
+        if (comSettingVo.equals(null)) {
+            return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
+        }
+        //todo 后台可配置,获取一个链上数据
+        Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = 0;
+        //1.先判断用户是否有足够的体力,根据snb判断。2. 收取到果实,扣除用户一个体力值
+        ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+        ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(userId);
+        Integer _out = _configStrength - Math.abs(playersAttribute.getStrength());
+        if (comUsersVo.getSnb() < comSettingVo.getLeastSnb()) {
+            //判断是否有双倍体力
+            if (_out < comSettingVo.getSnbUnitStrength()) {
+                map.put("msg", "需要双倍体力:" + comSettingVo.getSnbUnitStrength());
+                return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
+            }
+        } else {
+            //正常判断体力
+            if (_out < comSettingVo.getUnitStrength()) {
+                map.put("msg", "需要单倍体力:" + comSettingVo.getUnitStrength());
+                return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
+            }
+        }
+
+        List<Map> _stealLandInfos = new ArrayList<>();
+        Double _finalStealAmountSum = 0d;
+        //偷取用户的id
+        List<ComPlayerLand> otherPlayerLands = comPlayerLandService.findAllByCanStealOtherLands(userId, otherUserId);
+        if (otherPlayerLands.size() == 0) {
+            return Result.of(null, false, ResultEnum.LAND_CAN_STEAL_IS_ZERO.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_ZERO.getCode());
+        }
+
+        for (int i = 0; i < otherPlayerLands.size(); i++) {
+            ComPlayerLand otherPlayerLand = otherPlayerLands.get(i);
+            //获取当前种植的种子
+            ComMallSeedVo comMallSeedVo = comMallSeedService.findById(otherPlayerLand.getPlantId());
+            //需要redis 加锁
+            long time = System.currentTimeMillis() + TIMEOUT;
+            //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
+            String _redisKey = otherPlayerLand.getPlantFlag();
+            if (!StringUtils.hasText(_redisKey)) {
+                //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
+                _redisKey = otherPlayerLand.getUserId() + "or" + otherPlayerLand.getConfigLandId();
+            }
+            try {
+                if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                    //如果有冲突锁,跳过
+                    continue;
+                }
+                //todo 如果当前人员偷窃水果。记录一个信息,存储当前玩家已偷过的水果的信息
+                //计算一个偷取的收获量, 租赁倍数* 租赁日期下的产量
+                Integer _otherAmount = 0;
+                if (otherPlayerLand.getLeaseDate().equals(1)) {
+                    _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
+                } else if (otherPlayerLand.getLeaseDate().equals(2)) {
+                    _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
+                } else if (otherPlayerLand.getLeaseDate().equals(3)) {
+                    _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
+                }
+                //todo 拿出计算利润,收获量减去种子的成本(snb)后的百分之30 ,后面需要后台可调整
+                Integer _profit = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
+                // 配置的参数。这里先直接定义
+                Double profitConfig = comSettingVo.getProfit(), stealRatioMaxConfig = comSettingVo.getStealMaxRatio(), stealRatioMinConfig = comSettingVo.getStealMinRatio(), finallyGetRatioConfig = comSettingVo.getFinalRatio();
+                Double _stealRatio = new Random().nextDouble() * DoubleUtil.sub(stealRatioMaxConfig, stealRatioMinConfig) + stealRatioMinConfig;// 1%-3%
+                //todo 被偷取的人扣除 一个损失量,初利润算 _profit
+                Double _stolenAmount = DoubleUtil.mul(_profit.doubleValue(), _stealRatio);
+                //这里根据plantFlag判断目标用户当前种植被偷取完,看下是否需要处理更新前端信息,暂不处理
+                Double _sumStolen = comPlayerProfitService.getStolenSumByPlantFlag(otherPlayerLand.getPlantFlag());
+                //todo 这里的可偷利润应该是最大值,用户不能超过这个,需要限制判断
+                Double _maxAmount = DoubleUtil.mul(_profit.doubleValue(), profitConfig); //可偷取的利润
+                //1 就是 _sumStolen>_maxAmount
+                if (DoubleUtil.compare(_sumStolen, _maxAmount).equals(1)) {
+                    // 需要redis 解锁
+                    redisLock.unlock(_redisKey, String.valueOf(time));
+                    continue;
+                }
+                //最终偷窃人获取的是偷取的是目标用户损失量的10% finallyGetRatioConfig
+                Double _finalStealAmount = DoubleUtil.mul(_stolenAmount, finallyGetRatioConfig);
+                //偷窃后,系统回收部分
+                Double _lostStealAmount = DoubleUtil.sub(1d, finallyGetRatioConfig) * _stolenAmount;
+                //果实 Type =1
+                //todo 增加一个字段处理背包果实,拿出当前用户背包果实
+                ComPlayerGoods comPlayerGoods = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
+                Double _beforeStealAmount = 0.0;
+                if (comPlayerGoods == null) {
+                    //背包增加收取到别的用户对应的类型数量。比如当前是偷取到的果实
+                    comPlayerGoods = new ComPlayerGoods();
+                    comPlayerGoods.setUserId(userId);
+                    comPlayerGoods.setGoodsIndex(comMallSeedVo.getHarvestId());
+                    comPlayerGoods.setGoodsType(1);
+                    comPlayerGoods.setName(comMallSeedVo.getHarvestName());
+                    //用种子的picture
+                    comPlayerGoods.setPictureName(comMallSeedVo.getPicture());
+                    //amount 设置0
+                    comPlayerGoods.setAmount(0);
+                    comPlayerGoods.setAmountPart(_finalStealAmount);
+                    _beforeStealAmount = 0.0;
+                } else {
+                    _beforeStealAmount = comPlayerGoods.getAmountPart();
+                    //修改偷取字段
+                    comPlayerGoods.setAmountPart(DoubleUtil.add(comPlayerGoods.getAmountPart(), _finalStealAmount));
+                }
+                ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoods, ComPlayerGoodsVo.class);
+                comPlayerGoodsService.save(comPlayerGoodsVo);
+
+                //todo 偷窃损失,处理目标用户收取果实时候,减扣一部分被偷取的数量
+                ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
+                comPlayerProfit.setUserId(userId);
+                comPlayerProfit.setTargetId(otherUserId);
+                comPlayerProfit.setPlantFlag(otherPlayerLand.getPlantFlag());
+                comPlayerProfit.setLandId(otherPlayerLand.getConfigLandId());
+                comPlayerProfit.setLeaseMultiple(otherPlayerLand.getLeaseMultiple());
+                comPlayerProfit.setLeaseDate(otherPlayerLand.getLeaseDate());
+                comPlayerProfit.setHarvest(_otherAmount);
+                comPlayerProfit.setProfit(_profit.doubleValue());//目标用户可偷的初始利润值
+                comPlayerProfit.setStolen(_stolenAmount);//目标用户被偷的数量
+                comPlayerProfit.setFinalSteal(_finalStealAmount);//用户最终偷取的量,是被偷的数量 10%左右
+                comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(_stolenAmount, _sumStolen))); //可偷的减去被偷的
+                //记录相关比例
+                comPlayerProfit.setProfitRatio(profitConfig);
+                comPlayerProfit.setStealRatio(_stealRatio);
+                comPlayerProfit.setFinalRatio(finallyGetRatioConfig);
+                ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
+                comPlayerProfitService.save(comPlayerProfitVo);
+
+                //todo 记录一个收获的操作日志,这里由于偷取果实是有小数点的,小数点处理成整数,单位 暂定5位 100000
+                //      这里的数量都与偷窃知道相关。amountPart,注意不是果实实际总数 amount
+                ComPlayerLog _playerLog = new ComPlayerLog();
+                _playerLog.setUserId(userId);
+                _playerLog.setTId(comMallSeedVo.getHarvestId());
+                _playerLog.setTName(comMallSeedVo.getHarvestName());
+                _playerLog.setTType(6);//偷取果实时候,type设置6
+                _playerLog.setTAmount(0);
+                _playerLog.setBeforeAmount(comPlayerGoods.getAmount());
+                _playerLog.setAfterAmount(comPlayerGoods.getAmount());
+                //收取时候信息记录
+                _playerLog.setTPart(_finalStealAmount);
+                _playerLog.setTLoss(_lostStealAmount); //损失的部分
+                _playerLog.setBeforePart(_beforeStealAmount);
+                _playerLog.setAfterPart(comPlayerGoods.getAmountPart());
+                _playerLog.setLMultiple(otherPlayerLand.getLeaseMultiple());
+                ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
+                comPlayerLogService.save(_playerLogVo);
+
+                //todo 成功收取记录一个土地id
+                Map _landMap = new HashMap();
+                //记录一个id
+                _landMap.put("landId", otherPlayerLand.getConfigLandId());
+                //
+                _landMap.put("stealAmount", _finalStealAmount);
+                _finalStealAmountSum = DoubleUtil.add(_finalStealAmount, _finalStealAmountSum);
+                _stealLandInfos.add(_landMap);
+                // 需要redis 解锁
+                redisLock.unlock(_redisKey, String.valueOf(time));
+            } catch (Exception e) {
+                // 需要redis 解锁
+                redisLock.unlock(_redisKey, String.valueOf(time));
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+
+        map.put("msg", "偷取果实.");
+        map.put("steals", _stealLandInfos);
+        map.put("stealSum", _finalStealAmountSum);
+
+        if (_stealLandInfos.size() > 0) {
+            //todo 体力值可以后台配置
+            Integer _addStrength = comUsersVo.getSnb() < comSettingVo.getLeastSnb() ? comSettingVo.getSnbUnitStrength() : comSettingVo.getUnitStrength();
+            playersAttribute.setStrength(playersAttribute.getStrength() + _addStrength);
+            comPlayersAttriService.save(playersAttribute);
+            ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
+            //前端的显示,输出一个不小于0的体力值
+            Integer _outEnd = _configStrength - Math.abs(playersAttribute.getStrength());
+            comPlayersAttriSimpleVo.setCurrentStrength(_outEnd < 0 ? 0 : _outEnd);
+            //最大值是配置的值和链上数据的值相加
+            comPlayersAttriSimpleVo.setMaxStrength(_configStrength + _chainStrength);
+
+            map.put("playerAttribute", comPlayersAttriSimpleVo);
+        }
+
         return Result.of(map);
     }
 
@@ -296,8 +590,10 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         if (comPlayerGoodsSimpleVo == null) {
             return Result.of(null, false, ResultEnum.FRUIT_DATA_ERROR.getMessage(), ResultEnum.FRUIT_DATA_ERROR.getCode());
         }
-
-        if (amount > comPlayerGoodsSimpleVo.getAmount()) {
+        //添加了 amountPart,需要加入判断整数部分
+        Integer _userFloorAmount = comPlayerGoodsSimpleVo.getAmount() + (int) Math.floor(comPlayerGoodsSimpleVo.getAmountPart());
+        //旧判断 amount > comPlayerGoodsSimpleVo.getAmount()
+        if (amount > _userFloorAmount) {
             return Result.of(null, false, ResultEnum.FRUIT_AMOUNT_ERROR.getMessage(), ResultEnum.FRUIT_AMOUNT_ERROR.getCode());
         }
         //todo 销售果实时候,收取5%手续费,最少出售20的倍数
@@ -309,15 +605,58 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         try {
             Integer _selfBeforeFruitAmount = comPlayerGoodsSimpleVo.getAmount();
             Integer _selfAfterFruitAmount = 0;
-            if (comPlayerGoodsSimpleVo.getAmount().equals(amount)) {
-                //如果库存量和出售的果实数量一样,删除
-                comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
-                _selfAfterFruitAmount = 0;
-            } else {
-                comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - amount);
+            Double _selfBeforeFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
+            Double _selfAfterFruitAmountPart = 0d;
+            Integer _tAmount = 0;
+            Double _tAmountPart = 0d;
+
+            //if (comPlayerGoodsSimpleVo.getAmount().equals(amount)) {
+            //    //如果库存量和出售的果实数量一样,删除
+            //    comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
+            //    _selfAfterFruitAmount = 0;
+            //} else {
+            //    comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - amount);
+            //    _selfAfterFruitAmount = comPlayerGoodsSimpleVo.getAmount();
+            //    ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
+            //    comPlayerGoodsService.save(comPlayerGoodsVo);
+            //}
+            Integer _amountDif = comPlayerGoodsSimpleVo.getAmount() - amount;
+            //优先处理背包的amount
+            if (_amountDif > 0) {
+                //当前交易值
+                _tAmount = amount;
+                //如果amount 数量足够,直接记录 他们的差值
+                comPlayerGoodsSimpleVo.setAmount(_amountDif);
                 _selfAfterFruitAmount = comPlayerGoodsSimpleVo.getAmount();
+                _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
                 ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
                 comPlayerGoodsService.save(comPlayerGoodsVo);
+            } else {
+                _selfAfterFruitAmount = 0;
+
+                //保证精度
+                BigDecimal bigDecimal1 = new BigDecimal(Double.toString(_amountDif));
+                BigDecimal bigDecimal2 = new BigDecimal(Double.toString(comPlayerGoodsSimpleVo.getAmountPart()));
+                BigDecimal _amountPart = bigDecimal1.add(bigDecimal2);
+
+                //当前交易值,_amountDif 小于0 说明 amount 是全全部扣除,到小数部分了。
+                _tAmount = comPlayerGoodsSimpleVo.getAmount();
+                _tAmountPart = Math.abs(bigDecimal1.doubleValue());
+
+                System.out.print("_amountPart{}," + _amountPart.doubleValue());
+                //前面判断了。所以 _amountPart 不会比0.0小
+                if (_amountPart.compareTo(new BigDecimal(0.0)) <= 0) {
+                    //如果库存量 amount 和 amountPart 都为零,删除
+                    comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
+                    //这里记录一下,看是否会是一个负数
+                    _selfAfterFruitAmountPart = _amountPart.doubleValue();
+                } else {
+                    comPlayerGoodsSimpleVo.setAmount(0);
+                    comPlayerGoodsSimpleVo.setAmountPart(_amountPart.doubleValue());
+                    _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
+                    ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
+                    comPlayerGoodsService.save(comPlayerGoodsVo);
+                }
             }
             //todo 收取手续费之后
             int _endAmount = (int) (amount * 1);
@@ -359,10 +698,15 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             _saleFruitPlayerLog.setTId(comFruitVo.getId());
             _saleFruitPlayerLog.setTName(comFruitVo.getName());
             _saleFruitPlayerLog.setTType(5);//出售水果时候,type设置5
-            _saleFruitPlayerLog.setTAmount(amount);
+            _saleFruitPlayerLog.setTAmount(_tAmount);
             _saleFruitPlayerLog.setBeforeAmount(_selfBeforeFruitAmount);
             ////交易后的数据
             _saleFruitPlayerLog.setAfterAmount(_selfAfterFruitAmount);
+            //增加一个小数部分记录
+            _saleFruitPlayerLog.setTPart(_tAmountPart);
+            _saleFruitPlayerLog.setTLoss(0d);
+            _saleFruitPlayerLog.setBeforePart(_selfBeforeFruitAmountPart);
+            _saleFruitPlayerLog.setAfterPart(_selfAfterFruitAmountPart);
             _saleFruitPlayerLog.setLMultiple(0);//收获时候,会有一个倍数
             ComPlayerLogVo _saleFruitPlayerLogVo = CopyUtil.copy(_saleFruitPlayerLog, ComPlayerLogVo.class);
             comPlayerLogService.save(_saleFruitPlayerLogVo);
@@ -415,25 +759,65 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         if (comPlayerGoodsSimpleVo == null) {
             return Result.of(null, false, ResultEnum.FRUIT_DATA_ERROR.getMessage(), ResultEnum.FRUIT_DATA_ERROR.getCode());
         }
-
-        if (amount > comPlayerGoodsSimpleVo.getAmount()) {
+        //添加了 amountPart,需要加入判断整数部分
+        Integer _userFloorAmount = comPlayerGoodsSimpleVo.getAmount() + (int) Math.floor(comPlayerGoodsSimpleVo.getAmountPart());
+        if (amount > _userFloorAmount) {
             return Result.of(null, false, ResultEnum.FRUIT_AMOUNT_ERROR.getMessage(), ResultEnum.FRUIT_AMOUNT_ERROR.getCode());
         }
         try {
-            Integer _selfBeforeAmount = 0;
+            Integer _selfBeforeAmount = comPlayerGoodsSimpleVo.getAmount();
             Integer _selfAfterAmount = 0;
-            if (comPlayerGoodsSimpleVo.getAmount().equals(amount)) {
-                _selfBeforeAmount = comPlayerGoodsSimpleVo.getAmount();
-                //如果库存量和出售的果实数量一样,删除
-                comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
-                _selfAfterAmount = 0;
-            } else {
-                _selfBeforeAmount = comPlayerGoodsSimpleVo.getAmount();
-                comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - amount);
+            Double _selfBeforeFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
+            Double _selfAfterFruitAmountPart = 0d;
+            Integer _tAmount = 0;
+            Double _tAmountPart = 0d;
+
+            //if (comPlayerGoodsSimpleVo.getAmount().equals(amount)) {
+            //    //如果库存量和出售的果实数量一样,删除
+            //    comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
+            //    _selfAfterAmount = 0;
+            //} else {
+            //    comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - amount);
+            //    _selfAfterAmount = comPlayerGoodsSimpleVo.getAmount();
+            //    ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
+            //    comPlayerGoodsService.save(comPlayerGoodsVo);
+            //}
+            Integer _amountDif = comPlayerGoodsSimpleVo.getAmount() - amount;
+            //优先处理背包的amount
+            if (_amountDif > 0) {
+                //当前交易值
+                _tAmount = amount;
+                //如果amount 数量足够,直接记录 他们的差值
+                comPlayerGoodsSimpleVo.setAmount(_amountDif);
                 _selfAfterAmount = comPlayerGoodsSimpleVo.getAmount();
+                _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
                 ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
                 comPlayerGoodsService.save(comPlayerGoodsVo);
+            } else {
+                _selfAfterAmount = 0;
+                //保证精度
+                BigDecimal bigDecimal1 = new BigDecimal(Double.toString(_amountDif));
+                BigDecimal bigDecimal2 = new BigDecimal(Double.toString(comPlayerGoodsSimpleVo.getAmountPart()));
+                BigDecimal _amountPart = bigDecimal1.add(bigDecimal2);
+                //当前交易值,_amountDif 小于0 说明 amount 是全全部扣除,到小数部分了。
+                _tAmount = comPlayerGoodsSimpleVo.getAmount();
+                _tAmountPart = Math.abs(bigDecimal1.doubleValue());
+                System.out.print("_amountPart{}," + _amountPart.doubleValue());
+                //前面判断了。所以 _amountPart 不会比0.0小
+                if (_amountPart.compareTo(new BigDecimal(0.0)) <= 0) {
+                    //如果库存量 amount 和 amountPart 都为零,删除
+                    comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
+                    //这里记录一下,看是否会是一个负数
+                    _selfAfterFruitAmountPart = _amountPart.doubleValue();
+                } else {
+                    comPlayerGoodsSimpleVo.setAmount(0);
+                    comPlayerGoodsSimpleVo.setAmountPart(_amountPart.doubleValue());
+                    _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
+                    ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
+                    comPlayerGoodsService.save(comPlayerGoodsVo);
+                }
             }
+
             //todo 发送果实,记录当前用户的playerLog
             //当前用户
             ComPlayerLog _selfPlayerLog = new ComPlayerLog();
@@ -478,10 +862,16 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             _targetPlayerLog.setTId(comFruitVo.getId());
             _targetPlayerLog.setTName(comFruitVo.getName());
             _targetPlayerLog.setTType(3);//接收用户赠送水果,type设置 3
-            _targetPlayerLog.setTAmount(amount);
+            _targetPlayerLog.setTAmount(_tAmount);
             _targetPlayerLog.setBeforeAmount(_targetBeforeAmount);
             ////交易后的数据
             _targetPlayerLog.setAfterAmount(_targetAfterAmount);
+            //增加一个小数部分记录
+            _targetPlayerLog.setTPart(_tAmountPart);
+            _targetPlayerLog.setTLoss(0d);
+            _targetPlayerLog.setBeforePart(_selfBeforeFruitAmountPart);
+            _targetPlayerLog.setAfterPart(_selfAfterFruitAmountPart);
+
             _targetPlayerLog.setLMultiple(0);
             ComPlayerLogVo _targetPlayerLogVo = CopyUtil.copy(_targetPlayerLog, ComPlayerLogVo.class);
             comPlayerLogService.save(_targetPlayerLogVo);

+ 2 - 0
src/main/java/com/td/boss/game/complayergoods/pojo/ComPlayerGoods.java

@@ -24,6 +24,8 @@ public class ComPlayerGoods implements Serializable {
 
     private Integer amount;//数量
 
+    private Double amountPart;//部分数量,处理收取其他用户数据为主
+
     private Date createTime;
 
 }

+ 2 - 0
src/main/java/com/td/boss/game/complayergoods/vo/ComPlayerGoodsVo.java

@@ -20,6 +20,8 @@ public class ComPlayerGoodsVo extends PageCondition implements Serializable {
 
     private Integer amount;//数量
 
+    private Double amountPart;//部分数量,处理收取其他用户数据为主
+
     private Date createTime;
 
 }

+ 115 - 4
src/main/java/com/td/boss/game/complayerland/controller/ComPlayerLandController.java

@@ -11,24 +11,30 @@ import com.td.boss.game.complayergoods.pojo.ComPlayerGoods;
 import com.td.boss.game.complayergoods.service.ComPlayerGoodsService;
 import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerland.pojo.ComPlayerLandAndCanSteal;
 import com.td.boss.game.complayerland.vo.ComPlayerLandAndPlantVo;
+import com.td.boss.game.complayerland.vo.ComPlayerLandAndUserInfoVo;
 import com.td.boss.game.complayerland.vo.ComPlayerLandSimpleVo;
 import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
 import com.td.boss.game.complayerland.service.ComPlayerLandService;
-import com.td.boss.game.complayerlog.pojo.ComPlayerLog;
 import com.td.boss.game.complayerlog.service.ComPlayerLogService;
 import com.td.boss.game.complayerlog.vo.ComPlayerLogVo;
-import com.td.boss.game.comusers.vo.ComUsersSimpleVo;
 import com.td.boss.util.CopyUtil;
 import com.td.boss.util.DateUtil;
+import com.td.boss.util.UUIDUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.*;
 import java.util.stream.Collectors;
 
 @RestController
+@Slf4j
 @RequestMapping("/game/comPlayerLand/")
 public class ComPlayerLandController extends CommonController<ComPlayerLandVo, ComPlayerLand, Integer> {
 
@@ -50,13 +56,21 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
 
     /**
      * 获取用户土地
+     * 新增获取其他玩家用户土地信息,简单区分
      *
      * @param userId
      * @return
      */
     @GetMapping("getList")
-    public Result<List<ComPlayerLandAndPlantVo>> getLandFunction(@RequestParam(value = "userId") String userId) {
-        List<ComPlayerLand> comPlayerLands = comPlayerLandService.findAllByUserId(userId);
+    public Result<List<ComPlayerLandAndPlantVo>> getLandFunction(@RequestParam(value = "userId") String userId,
+                                                                 @RequestParam(value = "otherUserId", required = false) String otherUserId) {
+        String _currentUserId = userId;
+        //todo 新增获取其他用户信息
+        if (StringUtils.hasText(otherUserId)) {
+            _currentUserId = otherUserId;
+        }
+        log.info("获取土地时候的userId:" + _currentUserId);
+        List<ComPlayerLand> comPlayerLands = comPlayerLandService.findAllByUserId(_currentUserId);
         List<ComPlayerLandAndPlantVo> _simpleVoList = CopyUtil.copyList(comPlayerLands, ComPlayerLandAndPlantVo.class);
         List<ComPlayerLandAndPlantVo> _list = new ArrayList<>();
 
@@ -130,6 +144,78 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
     }
 
 
+    /**
+     * 获取可偷取的土地列表
+     * 也可以获取自己的可偷列表
+     *
+     * @param userId
+     * @return 返回的是已经过滤租赁过期但未删除的的列表
+     */
+    @GetMapping("getCanStealDetailList")
+    public Result<List<ComPlayerLandAndPlantVo>> getCanStealListFunction(@RequestParam(value = "userId") String userId,
+                                                                 @RequestParam(value = "otherUserId", required = false) String otherUserId) {
+        String _currentUserId = userId;
+        //todo 新增获取其他用户信息
+        if (StringUtils.hasText(otherUserId)) {
+            _currentUserId = otherUserId;
+        }
+        List<ComPlayerLandAndCanSteal> comPlayerLands = comPlayerLandService.findCanStealByUserId(_currentUserId);
+        List<ComPlayerLandAndPlantVo> _simpleVoList = CopyUtil.copyList(comPlayerLands, ComPlayerLandAndPlantVo.class);
+        List<ComPlayerLandAndPlantVo> _list = new ArrayList<>();
+        try {
+            _simpleVoList.stream().map(e -> {
+                ComPlayerLandAndPlantVo comPlayerLandAndPlantVo = e;
+                //todo 返回一个计算的天数和小时,解决跨时区的问题
+                //租赁的剩余天数 。 测试:DateUtil.getNowDateAddYear(1).getTime(); DateUtil.getNowDate().getTime()
+                Long leaseDaysMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
+                //这里不需要处理租赁过期判断
+                //土地时间
+                //租赁的总时间 = 租赁时间 - 土地数据的创建时间
+                Long leaseAllMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - comPlayerLandAndPlantVo.getCreateTime().getTime();
+                Integer allDays = DateUtil.getDays(leaseAllMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseAllMill).intValue();
+                comPlayerLandAndPlantVo.setLeaseDays(allDays);
+                Integer leaseDays = DateUtil.getDays(leaseDaysMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseDaysMill).intValue();
+                comPlayerLandAndPlantVo.setLeaseDaysRemaining(leaseDays);
+                //返回一个租赁时间毫秒
+                comPlayerLandAndPlantVo.setLeaseDaysMill(leaseDaysMill);
+
+                // 如果种植了,返回一个种植数据
+                if (comPlayerLandAndPlantVo.getIsPlant().equals(1)) {
+                    ComMallSeedVo comMallSeedVo = comMallSeedService.findById(comPlayerLandAndPlantVo.getPlantId());
+                    comPlayerLandAndPlantVo.setSeedInfo(comMallSeedVo);
+                    //种子时间
+                    //当前时间 > 种植时间+成熟期  = 说明可以收获了
+                    //获取当前时间 - 植物的成熟期 = 收获时间,收获时间 >= 种植时间,即可以收获
+                    Date _harvestTime = DateUtil.getNowDateMinusDay(comMallSeedVo.getMaturity());
+                    // 两个时间差, 逻辑是_harvestTime 时间慢慢接近种植时间
+                    long diff = comPlayerLandAndPlantVo.getPlantStart().getTime() - _harvestTime.getTime();
+                    //种植的剩余时间毫秒
+                    comPlayerLandAndPlantVo.setPlantDaysMill(diff);
+                    if (diff <= 0) {
+                        //说明可以收获了
+                        comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
+                        comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
+                    } else {
+                        comPlayerLandAndPlantVo.setPlantDaysRemaining(DateUtil.getDays(diff).intValue());
+                        comPlayerLandAndPlantVo.setPlantHoursRemaining(DateUtil.getHours(diff).intValue());
+                    }
+                } else {
+                    //未种植时候,设置为0
+                    comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
+                    comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
+                }
+
+                return _list.add(e);
+            }).collect(Collectors.toList());
+
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+
+        return Result.of(_list);
+    }
+
+
     /**
      * 获取租赁土地状态,如果webSocket未通,
      * 使用轮询方法查询更新租赁状态
@@ -263,6 +349,10 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
             comPlayerLand.setPlantStart(new Date());
             //种植天数,成熟天数
             comPlayerLand.setPlantMature(comMallSeedVo.getMaturity());
+
+            //生成一个标识,用来识别种植
+            comPlayerLand.setPlantFlag(UUIDUtil.getUUID());
+
             //comPlayerLand.setLandDescribe();
             ComPlayerLandVo comPlayerLandVo = CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class);
             comPlayerLandService.save(comPlayerLandVo);
@@ -321,4 +411,25 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
             throw new RuntimeException(e.getMessage());
         }
     }
+
+
+    /**
+     * 获取存在可偷取的用户列表
+     *
+     * @param userId
+     * @return
+     */
+    @GetMapping("getCanStealUserList")
+    public Result<List<ComPlayerLandAndUserInfoVo>> getCanStealUserList(
+            @RequestParam(value = "userId") String userId,
+            @RequestParam(value = "page", defaultValue = "0") Integer page,
+            @RequestParam(value = "limit", defaultValue = "10") Integer limit
+    ) {
+
+        PageRequest pageable = PageRequest.of(page, limit, Sort.by(Sort.Direction.DESC, "plant_start"));
+
+        List<ComPlayerLandAndUserInfoVo> comPlayerLands = comPlayerLandService.findAllByCanStealNotSelf(userId, pageable);
+
+        return Result.of(comPlayerLands);
+    }
 }

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLand.java

@@ -36,6 +36,8 @@ public class ComPlayerLand implements Serializable {
 
     private Integer plantMature;//成熟期
 
+    private String plantFlag;//每次种植生成一个唯一标识
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;

+ 54 - 0
src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLandAndCanSteal.java

@@ -0,0 +1,54 @@
+package com.td.boss.game.complayerland.pojo;
+
+import com.td.boss.game.commallseed.vo.ComMallSeedVo;
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@Entity //这个注解必备
+public class ComPlayerLandAndCanSteal implements Serializable {
+
+    @Id //这个注解必备
+    @GeneratedValue(strategy= GenerationType.IDENTITY)
+    private Integer id;
+
+    private Integer configLandId;
+
+    private String userId;
+
+    private String name;//名字
+
+    private Integer isLease;//是否租赁
+
+    private Date leaseTime;//租赁时间
+
+    private Integer leaseMultiple;//租赁的倍数
+
+    private Integer leaseDate;//租赁的日期,1是3个月,2是1年,3是5年
+
+    private Integer isPlant;//是否种植
+
+    private Integer plantId;//种植植物的id
+
+    private Date plantStart;//种植开始时间
+
+    private Integer plantMature;//成熟期
+
+    private String plantFlag;//每次种植生成一个唯一标识
+
+    private String landDescribe;//土地描述
+
+    private Double rentalExpenses;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    private Integer canSteal;
+}

+ 25 - 4
src/main/java/com/td/boss/game/complayerland/repository/ComPlayerLandRepository.java

@@ -1,9 +1,10 @@
 package com.td.boss.game.complayerland.repository;
 
 import com.td.boss.common.repository.*;
-import com.td.boss.game.comconfigland.pojo.ComConfigLand;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
-import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
+import com.td.boss.game.complayerland.vo.ComPlayerLandAndUserInfoVo;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 
 import java.util.List;
@@ -12,9 +13,29 @@ import java.util.Optional;
 @Repository
 public interface ComPlayerLandRepository extends CommonRepository<ComPlayerLand, Integer> {
 
-    List<ComPlayerLand>  findAllByUserId(String userId);
+    List<ComPlayerLand> findAllByUserId(String userId);
 
-    Optional<ComPlayerLand> findByUserIdAndConfigLandId(String userId,Integer landId);
+
+    @Query(value = "SELECT\n" +
+            "a.user_id,\n" +
+            "a.is_plant,\n" +
+            "a.plant_start,\n" +
+            "a.plant_mature,\n" +
+            "DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) AS mature_date,\n" +
+            "b.address,\n" +
+            "(CASE WHEN c.id IS NULL THEN 1 ELSE c.id END) AS can_steal\n" +
+            "FROM\n" +
+            "com_player_land AS a \n" +
+            "LEFT JOIN com_users AS b ON a.user_id = b.user_id\n" +
+            "LEFT JOIN com_player_profit AS c ON c.user_id = :userId  AND a.config_land_id = c.land_id AND (ISNULL(c.plant_flag) = 1 OR a.plant_flag = c.plant_flag) \n" +
+            "WHERE NOT(a.user_id = :userId) AND is_lease = 1 AND is_plant = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW()\n" +
+            "AND DATE(a.lease_time) > DATE(NOW()) GROUP BY a.user_id , can_steal HAVING can_steal = 1", nativeQuery = true)
+    List<Object> findAllIsStealComPlayerLandAndUserInfo(String userId,Pageable pageable);
+
+
+    List<ComPlayerLand> findAllByUserIdAndIsLeaseAndIsPlant(String userId, Integer isLease, Integer isPlant);
+
+    Optional<ComPlayerLand> findByUserIdAndConfigLandId(String userId, Integer landId);
 
     Optional<ComPlayerLand> findByConfigLandId(Integer landId);
 }

+ 15 - 1
src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandService.java

@@ -1,9 +1,12 @@
 package com.td.boss.game.complayerland.service;
 
 import com.td.boss.common.service.*;
-import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerland.pojo.ComPlayerLandAndCanSteal;
+import com.td.boss.game.complayerland.vo.ComPlayerLandAndPlantVo;
+import com.td.boss.game.complayerland.vo.ComPlayerLandAndUserInfoVo;
 import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
+import org.springframework.data.domain.Pageable;
 
 import java.util.List;
 
@@ -11,6 +14,17 @@ public interface ComPlayerLandService extends CommonService<ComPlayerLandVo, Com
 
     List<ComPlayerLand> findAllByUserId(String userId);
 
+    //获取可以偷取的土地用户,用于首页偷菜列表显示,返回一个不包括自己的列表
+    List<ComPlayerLandAndUserInfoVo> findAllByCanStealNotSelf(String userId, Pageable pageable);
+
+    //根据userId 获取可偷取的参数
+    List<ComPlayerLandAndCanSteal> findCanStealByUserId(String userId);
+
+    List<ComPlayerLandAndUserInfoVo> findAllByCanStealAndOtherUser(String userId);
+
+    //获取当前用户的全部可偷土地
+    List<ComPlayerLand> findAllByCanStealOtherLands(String userId,String otherUserId);
+
     ComPlayerLand findById(Integer id);
 
     ComPlayerLand findByLandId(Integer id);

+ 66 - 3
src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandServiceImpl.java

@@ -1,27 +1,39 @@
 package com.td.boss.game.complayerland.service;
 
 import com.td.boss.common.service.*;
-import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerland.pojo.ComPlayerLandAndCanSteal;
+import com.td.boss.game.complayerland.vo.ComPlayerLandAndUserInfoVo;
 import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
 import com.td.boss.game.complayerland.repository.ComPlayerLandRepository;
+import com.td.boss.game.complayerprofit.service.ComPlayerProfitService;
+import com.td.boss.util.DateUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 @Service
 @Transactional
-public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo, ComPlayerLand, Integer> implements ComPlayerLandService{
+public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo, ComPlayerLand, Integer> implements ComPlayerLandService {
 
     @PersistenceContext
     private EntityManager em;
     @Autowired
     private ComPlayerLandRepository comPlayerLandRepository;
 
+    @Autowired
+    private ComPlayerProfitService comPlayerProfitService;
+
 
     @Override
     public List<ComPlayerLand> findAllByUserId(String userId) {
@@ -29,6 +41,55 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
     }
 
 
+    @Override
+    public List<ComPlayerLandAndUserInfoVo> findAllByCanStealNotSelf(String userId,Pageable pageable) {
+        List<Object> objects = comPlayerLandRepository.findAllIsStealComPlayerLandAndUserInfo(userId,pageable);
+        List<ComPlayerLandAndUserInfoVo> landAndUserInfoVos = new ArrayList<>();
+        for (int i = 0; i < objects.size(); i++) {
+            Object[] tempObj = (Object[]) objects.get(i);
+            landAndUserInfoVos.add(new ComPlayerLandAndUserInfoVo((String) tempObj[0], (Boolean) tempObj[1], (Date) tempObj[2], (Integer) tempObj[3], (Date) tempObj[4], (String) tempObj[5]));
+        }
+        return landAndUserInfoVos;
+    }
+
+    @Override
+    public List<ComPlayerLandAndCanSteal> findCanStealByUserId(String userId) {
+        String sql = "SELECT\n" +
+                "a.*,\n" +
+                "(CASE WHEN c.id IS NULL THEN 1 ELSE 0 END ) AS can_steal\n" +
+                "FROM\n" +
+                "com_player_land AS a \n" +
+                "LEFT JOIN com_player_profit AS c ON a.user_id = c.target_id  AND a.config_land_id = c.land_id AND (ISNULL(c.plant_flag) = 1 OR a.plant_flag = c.plant_flag)\n" +
+                "WHERE a.user_id = "+userId+" AND is_lease = 1 AND is_plant = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW()\n" +
+                "AND a.lease_time > NOW()";
+        Query nativeQuery = em.createNativeQuery(sql, ComPlayerLandAndCanSteal.class);
+        List list = nativeQuery.getResultList();
+        return list;
+    }
+
+    @Override
+    public List<ComPlayerLandAndUserInfoVo> findAllByCanStealAndOtherUser(String userId) {
+        return null;
+    }
+
+    @Override
+    public List<ComPlayerLand> findAllByCanStealOtherLands(String userId,String otherUserId) {
+        //查找目标
+        List<ComPlayerLand> comPlayerLandList = comPlayerLandRepository.findAllByUserIdAndIsLeaseAndIsPlant(otherUserId, 1, 1).stream()
+                .filter(
+                        e ->
+                                //过滤掉对应的条件
+                                //过滤掉未成熟的
+                                DateUtil.getOldDateAddDay(e.getPlantStart(), e.getPlantMature()).getTime() <= DateUtil.getNowDate().getTime()
+                                        &&
+                                        //判断是否偷取过目标的土地
+                                        comPlayerProfitService.findByUserIdAndTargetIdAndLandIdAndPlantFlag(userId,e.getUserId(), e.getConfigLandId(), e.getPlantFlag()) == null
+
+                )
+                .collect(Collectors.toList());
+        return comPlayerLandList;
+    }
+
     @Override
     public ComPlayerLand findById(Integer id) {
         Optional<ComPlayerLand> comPlayerLand = comPlayerLandRepository.findById(id);
@@ -46,11 +107,13 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
 
     @Override
     public ComPlayerLand findByUserIdAndLandId(String userId, Integer id) {
-        return comPlayerLandRepository.findByUserIdAndConfigLandId(userId,id).orElse(null);
+        return comPlayerLandRepository.findByUserIdAndConfigLandId(userId, id).orElse(null);
     }
 
     @Override
     public ComPlayerLand AddComPlayerLand(ComPlayerLand comPlayerLand) {
         return comPlayerLandRepository.save(comPlayerLand);
     }
+
+
 }

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandAndPlantVo.java

@@ -54,4 +54,6 @@ public class ComPlayerLandAndPlantVo implements Serializable {
     private Date createTime;
 
     private Date updateTime;
+
+    private Integer canSteal;
 }

+ 33 - 0
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandAndUserInfoVo.java

@@ -0,0 +1,33 @@
+package com.td.boss.game.complayerland.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2022/2/10
+ */
+@Getter
+@Setter
+@ToString
+public class ComPlayerLandAndUserInfoVo {
+    private String userId;
+    private Boolean isPlant;
+    private Date plantStart;
+    private Integer plantMature;
+    private Date matureDate;
+    private String address;
+
+    public ComPlayerLandAndUserInfoVo(String userId, Boolean isPlant, Date plantStart, Integer plantMature, Date matureDate, String address) {
+        this.userId = userId;
+        this.isPlant = isPlant;
+        this.plantStart = plantStart;
+        this.plantMature = plantMature;
+        this.matureDate = matureDate;
+        this.address = address;
+    }
+
+}

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandVo.java

@@ -33,6 +33,8 @@ public class ComPlayerLandVo extends PageCondition implements Serializable {
 
     private Integer plantMature;//成熟期
 
+    private String plantFlag;//每次种植生成一个唯一标识
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;

+ 8 - 0
src/main/java/com/td/boss/game/complayerlog/pojo/ComPlayerLog.java

@@ -27,6 +27,14 @@ public class ComPlayerLog implements Serializable {
 
     private Integer afterAmount;//交易后的数量
 
+    private Double tPart;//收取数量
+
+    private Double tLoss;//损失的果实部分
+
+    private Double beforePart;//收取交易前的数量
+
+    private Double afterPart;//收取交易后的数量
+
     private Integer lMultiple;//如果是操作土地相关,land 数据,记录一下倍数
 
     private Date createTime;//

+ 8 - 0
src/main/java/com/td/boss/game/complayerlog/vo/ComPlayerLogVo.java

@@ -27,6 +27,14 @@ public class ComPlayerLogVo extends PageCondition implements Serializable {
     @JsonProperty
     private Integer lMultiple;//如果是操作土地相关,land 数据,记录一下倍数
 
+    private Double tPart;//收取数量
+
+    private Double tLoss;//损失的果实部分
+
+    private Double beforePart;//收取交易前的数量
+
+    private Double afterPart;//收取交易后的数量
+
     private Date createTime;//
 
     private Date updateTime;//

+ 15 - 0
src/main/java/com/td/boss/game/complayerprofit/controller/ComPlayerProfitController.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.complayerprofit.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
+import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
+import com.td.boss.game.complayerprofit.service.ComPlayerProfitService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comPlayerProfit/")
+public class ComPlayerProfitController extends CommonController<ComPlayerProfitVo, ComPlayerProfit, String> {
+    @Autowired
+    private ComPlayerProfitService comPlayerProfitService;
+}

+ 47 - 0
src/main/java/com/td/boss/game/complayerprofit/pojo/ComPlayerProfit.java

@@ -0,0 +1,47 @@
+package com.td.boss.game.complayerprofit.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_player_profit")
+@Data
+public class ComPlayerProfit implements Serializable {
+    @Id
+    private String id;//
+
+    private String userId;//操作用户的id
+
+    private String targetId;//目标用户的id
+
+    private String plantFlag;//种植的唯一标识
+
+    private Integer landId;//收取土地id
+
+    private Integer leaseMultiple;//租赁的倍数
+
+    private Integer leaseDate;//租赁的日期,1是3个月,2是1年,3是5年
+
+    private Integer harvest;//记录一个收取变量
+
+    private Double profit;//处理的利润值,种植的就是对应果实
+
+    private Double profitAfter;//剩余的数量
+
+    private Double stolen;//目标损失的量
+
+    private Double finalSteal;//玩家最终偷取的数量
+
+    private Double profitRatio;//拿出用户收成的比例值作为利润,默认比例值设置是 20%
+
+    private Double stealRatio;//在可偷取的利润中,随机一个收取的比例区间。 默认是1%~3%
+
+    private Double finalRatio;//最后用户可收取的利润比例,目前是设置 10%
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 29 - 0
src/main/java/com/td/boss/game/complayerprofit/repository/ComPlayerProfitRepository.java

@@ -0,0 +1,29 @@
+package com.td.boss.game.complayerprofit.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface ComPlayerProfitRepository extends CommonRepository<ComPlayerProfit, String> {
+
+    /**
+     * 查询用户被偷取的信息,使用targetId
+     * @param targetId
+     * @param plantFlag
+     * @param landId
+     * @return
+     */
+    List<ComPlayerProfit> findByTargetIdAndPlantFlagAndLandId(String targetId, String plantFlag, Integer landId);
+
+    Optional<ComPlayerProfit> findByUserIdAndPlantFlag(String userId, String plantFlag);
+
+    Optional<ComPlayerProfit> findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId, String targetId, Integer landId, String plantFlag);
+
+    @Query(value = "SELECT IFNULL(sum(u.stolen), 0.0) AS sum FROM  com_player_profit u  where u.plant_flag = :plantFlag", nativeQuery = true)
+    Double getStolenSumByPlantFlag(String plantFlag);
+}

+ 26 - 0
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitService.java

@@ -0,0 +1,26 @@
+package com.td.boss.game.complayerprofit.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
+import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
+
+import java.util.List;
+
+public interface ComPlayerProfitService extends CommonService<ComPlayerProfitVo, ComPlayerProfit, String> {
+
+    /**
+     * 获取被偷取的信息,表里面 targetId 对应自己的用户的 userId
+     * @param userId
+     * @param plantFlag
+     * @param landId
+     * @return
+     */
+    List<ComPlayerProfit> findByUserIdAndPlantFlagAndLandId(String userId,String plantFlag,Integer landId);
+
+    ComPlayerProfit findByUserIdAndPlantFlag(String userId,String plantFlag);
+
+    ComPlayerProfit findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId,String targetId,Integer configLandId, String plantFlag);
+
+    Double getStolenSumByPlantFlag(String plantFlag);
+}

+ 42 - 0
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java

@@ -0,0 +1,42 @@
+package com.td.boss.game.complayerprofit.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
+import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
+import com.td.boss.game.complayerprofit.repository.ComPlayerProfitRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.List;
+
+@Service
+@Transactional
+public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfitVo, ComPlayerProfit, String> implements ComPlayerProfitService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComPlayerProfitRepository comPlayerProfitRepository;
+
+    @Override
+    public List<ComPlayerProfit> findByUserIdAndPlantFlagAndLandId(String userId, String plantFlag, Integer landId) {
+        return comPlayerProfitRepository.findByTargetIdAndPlantFlagAndLandId(userId,plantFlag,landId);
+    }
+
+    @Override
+    public ComPlayerProfit findByUserIdAndPlantFlag(String userId,String plantFlag) {
+        return comPlayerProfitRepository.findByUserIdAndPlantFlag(userId,plantFlag).orElse(null);
+    }
+
+    @Override
+    public ComPlayerProfit findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId,String targetId, Integer configLandId, String plantFlag) {
+        return comPlayerProfitRepository.findByUserIdAndTargetIdAndLandIdAndPlantFlag(userId,targetId,configLandId,plantFlag).orElse(null);
+    }
+
+    @Override
+    public Double getStolenSumByPlantFlag(String plantFlag) {
+        return comPlayerProfitRepository.getStolenSumByPlantFlag(plantFlag);
+    }
+}

+ 43 - 0
src/main/java/com/td/boss/game/complayerprofit/vo/ComPlayerProfitVo.java

@@ -0,0 +1,43 @@
+package com.td.boss.game.complayerprofit.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayerProfitVo extends PageCondition implements Serializable {
+    private String id;//
+
+    private String userId;//操作用户的id
+
+    private String targetId;//目标用户的id
+
+    private String plantFlag;//种植的唯一标识
+
+    private Integer landId;//收取土地id
+
+    private Integer leaseMultiple;//租赁的倍数
+
+    private Integer leaseDate;//租赁的日期,1是3个月,2是1年,3是5年
+
+    private Integer harvest;//记录一个收取变量
+
+    private Double profit;//处理的利润值,种植的就是对应果实
+
+    private Double profitAfter;//剩余的数量
+
+    private Double stolen;//目标损失的量
+
+    private Double finalSteal;//玩家最终偷取的数量
+
+    private Double profitRatio;//拿出用户收成的比例值作为利润,默认比例值设置是 20%
+
+    private Double stealRatio;//在可偷取的利润中,随机一个收取的比例区间。 默认是1%~3%
+
+    private Double finalRatio;//最后用户可收取的利润比例,目前是设置 10%
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 66 - 0
src/main/java/com/td/boss/game/complayersattri/controller/ComPlayersAttriController.java

@@ -0,0 +1,66 @@
+package com.td.boss.game.complayersattri.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.game.complayersattri.pojo.ComPlayersAttri;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriSimpleVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
+import com.td.boss.game.complayersattri.service.ComPlayersAttriService;
+import com.td.boss.game.comsetting.service.ComSettingService;
+import com.td.boss.game.comsetting.vo.ComSettingVo;
+import com.td.boss.util.CopyUtil;
+import com.td.boss.util.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/game/comPlayersAttri/")
+public class ComPlayersAttriController extends CommonController<ComPlayersAttriVo, ComPlayersAttri, Integer> {
+    @Autowired
+    private ComPlayersAttriService comPlayersAttriService;
+
+    @Autowired
+    private ComSettingService comSettingService;
+    /**
+     * 获取玩家属性
+     *
+     * @param userId
+     * @return
+     */
+    @GetMapping("getPlayerAttribute")
+    public Result<ComPlayersAttriSimpleVo> getPlayerAttributeFunction(@RequestParam(value = "userId") String userId) {
+        //获取数据库相关配置
+        ComSettingVo comSettingVo = comSettingService.get("1").getData();
+        if (comSettingVo.equals(null)) {
+            return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
+        }
+        //获取一下用户属性,新增表
+        ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(userId);
+        if (playersAttribute == null) {
+            // todo player 如果角色不存在的话,直接创建一个。
+            playersAttribute = new ComPlayersAttriVo();
+            playersAttribute.setUserId(userId);
+            playersAttribute.setStrength(0);
+            playersAttribute.setLucky(0);
+            playersAttribute.setResetStrength(DateUtil.getNowDate());
+            playersAttribute.setCreateTime(DateUtil.getNowDate());
+            playersAttribute.setUpdateTime(DateUtil.getNowDate());
+            comPlayersAttriService.save(playersAttribute);
+        }
+        ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
+        //todo 后台可配置,获取一个链上数据
+        Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = 0;
+        //前端的显示,输出一个不小于0的体力值
+        Integer _out = _configStrength - Math.abs(playersAttribute.getStrength());
+        comPlayersAttriSimpleVo.setCurrentStrength(_out < 0 ? 0 : _out);
+        //最大值是配置的值和链上数据的值相加
+        comPlayersAttriSimpleVo.setMaxStrength(_configStrength + _chainStrength);
+
+        return Result.of(comPlayersAttriSimpleVo);
+    }
+
+}

+ 29 - 0
src/main/java/com/td/boss/game/complayersattri/pojo/ComPlayersAttri.java

@@ -0,0 +1,29 @@
+package com.td.boss.game.complayersattri.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_players_attri")
+@Data
+public class ComPlayersAttri implements Serializable {
+    @Id
+    private String id;//该角色的id
+
+    private String userId;//创建该角色的用户id
+
+    private String name;//角色名词
+
+    private Integer strength;//体力值,初始0,记录使用的体力
+
+    private Integer lucky;//幸运值
+
+    private Date resetStrength;//重置体力的时间
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 15 - 0
src/main/java/com/td/boss/game/complayersattri/repository/ComPlayersAttriRepository.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.complayersattri.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.complayersattri.pojo.ComPlayersAttri;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
+import org.springframework.stereotype.Repository;
+
+import javax.swing.text.html.Option;
+import java.util.Optional;
+
+@Repository
+public interface ComPlayersAttriRepository extends CommonRepository<ComPlayersAttri, Integer> {
+
+    Optional<ComPlayersAttri> findByUserId(String userId);
+}

+ 9 - 0
src/main/java/com/td/boss/game/complayersattri/service/ComPlayersAttriService.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.complayersattri.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayersattri.pojo.ComPlayersAttri;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
+
+public interface ComPlayersAttriService extends CommonService<ComPlayersAttriVo, ComPlayersAttri, Integer> {
+    ComPlayersAttriVo findByUserId(String userId);
+}

+ 30 - 0
src/main/java/com/td/boss/game/complayersattri/service/ComPlayersAttriServiceImpl.java

@@ -0,0 +1,30 @@
+package com.td.boss.game.complayersattri.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayersattri.pojo.ComPlayersAttri;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
+import com.td.boss.game.complayersattri.repository.ComPlayersAttriRepository;
+import com.td.boss.util.CopyUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComPlayersAttriServiceImpl extends CommonServiceImpl<ComPlayersAttriVo, ComPlayersAttri, Integer> implements ComPlayersAttriService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComPlayersAttriRepository comPlayersAttriRepository;
+
+    @Override
+    public ComPlayersAttriVo findByUserId(String userId) {
+        ComPlayersAttri comPlayersAttri = comPlayersAttriRepository.findByUserId(userId).orElse(null);
+        return comPlayersAttri == null?null:CopyUtil.copy(comPlayersAttri,ComPlayersAttriVo.class);
+    }
+}

+ 26 - 0
src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersAttriSimpleVo.java

@@ -0,0 +1,26 @@
+package com.td.boss.game.complayersattri.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayersAttriSimpleVo implements Serializable {
+
+    private String name;//角色名词
+
+    private Integer currentStrength;//返回前端是计算的值,当前的体力值
+
+    private Integer MaxStrength;//返回前端是计算的值,最大体力
+
+    private Integer lucky;//幸运值
+
+    private Date resetStrength;//重置体力的时间
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 25 - 0
src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersAttriVo.java

@@ -0,0 +1,25 @@
+package com.td.boss.game.complayersattri.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayersAttriVo extends PageCondition implements Serializable {
+    private String id;//该角色的id
+
+    private String userId;//创建该角色的用户id
+
+    private String name;//角色名词
+
+    private Integer strength;//体力值,初始0,记录使用的体力
+
+    private Integer lucky;//幸运值
+
+    private Date resetStrength;//重置体力的时间
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 34 - 0
src/main/java/com/td/boss/game/comsetting/controller/ComSettingController.java

@@ -0,0 +1,34 @@
+package com.td.boss.game.comsetting.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.game.comsetting.pojo.ComSetting;
+import com.td.boss.game.comsetting.vo.ComSettingVo;
+import com.td.boss.game.comsetting.service.ComSettingService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comSetting/")
+public class ComSettingController extends CommonController<ComSettingVo, ComSetting, String> {
+    @Autowired
+    private ComSettingService comSettingService;
+
+
+    /**
+     * 获取游戏设置
+     *
+     * @param userId
+     * @return
+     */
+    @GetMapping("getGameSetting")
+    public Result<ComSettingVo> getGameSettingFunction(@RequestParam(value = "userId") String userId) {
+        //获取数据库相关配置
+        ComSettingVo comSettingVo = comSettingService.get("1").getData();
+        if (comSettingVo.equals(null)) {
+            return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
+        }
+        return Result.of(comSettingVo);
+    }
+}

+ 37 - 0
src/main/java/com/td/boss/game/comsetting/pojo/ComSetting.java

@@ -0,0 +1,37 @@
+package com.td.boss.game.comsetting.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_setting")
+@Data
+public class ComSetting implements Serializable {
+    @Id
+    private String id;//
+
+    private Integer maxLeaseMulti;//最大限制输入的租赁倍数
+
+    private Integer maxStrength;//设置的最大体力
+
+    private Integer unitStrength;//体力值变化的单位
+
+    private Integer snbUnitStrength;//走snb不足时候,用这个单位
+
+    private Integer leastSnb;//最小判断的snb
+
+    private Double profit;//玩家的种植可以被偷的利润比例,默认是0
+
+    private Double stealMaxRatio;//偷取的一个随机范围 比如 0.03 这样
+
+    private Double stealMinRatio;//偷取的一个随机范围 比如 0.01 这样
+
+    private Double finalRatio;//最后被偷取的比例,比如被偷取用户损失了10个,最后偷取的用户获得这10个乘这个比例
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/comsetting/repository/ComSettingRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.comsetting.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.comsetting.pojo.ComSetting;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComSettingRepository extends CommonRepository<ComSetting, String> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/comsetting/service/ComSettingService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.comsetting.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comsetting.pojo.ComSetting;
+import com.td.boss.game.comsetting.vo.ComSettingVo;
+
+public interface ComSettingService extends CommonService<ComSettingVo, ComSetting, String> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/comsetting/service/ComSettingServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.comsetting.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comsetting.pojo.ComSetting;
+import com.td.boss.game.comsetting.vo.ComSettingVo;
+import com.td.boss.game.comsetting.repository.ComSettingRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComSettingServiceImpl extends CommonServiceImpl<ComSettingVo, ComSetting, String> implements ComSettingService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComSettingRepository comSettingRepository;
+}

+ 34 - 0
src/main/java/com/td/boss/game/comsetting/vo/ComSettingSimpleVo.java

@@ -0,0 +1,34 @@
+package com.td.boss.game.comsetting.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComSettingSimpleVo  implements Serializable {
+
+    private Integer maxLeaseMulti;//最大限制输入的租赁倍数
+
+    private Integer maxStrength;//设置的最大体力
+
+    private Integer unitStrength;//体力值变化的单位
+
+    private Integer snbUnitStrength;//走snb不足时候,用这个单位
+
+    private Integer leastSnb;//最小判断的snb
+
+    private Double profit;//玩家的种植可以被偷的利润比例,默认是0
+
+    private Double stealMaxRatio;//偷取的一个随机范围 比如 0.03 这样
+
+    private Double stealMinRatio;//偷取的一个随机范围 比如 0.01 这样
+
+    private Double finalRatio;//最后被偷取的比例,比如被偷取用户损失了10个,最后偷取的用户获得这10个乘这个比例
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 33 - 0
src/main/java/com/td/boss/game/comsetting/vo/ComSettingVo.java

@@ -0,0 +1,33 @@
+package com.td.boss.game.comsetting.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComSettingVo extends PageCondition implements Serializable {
+    private String id;//
+
+    private Integer maxLeaseMulti;//最大限制输入的租赁倍数
+
+    private Integer maxStrength;//设置的最大体力
+
+    private Integer unitStrength;//体力值变化的单位
+
+    private Integer snbUnitStrength;//走snb不足时候,用这个单位
+
+    private Integer leastSnb;//最小判断的snb
+
+    private Double profit;//玩家的种植可以被偷的利润比例,默认是0
+
+    private Double stealMaxRatio;//偷取的一个随机范围 比如 0.03 这样
+
+    private Double stealMinRatio;//偷取的一个随机范围 比如 0.01 这样
+
+    private Double finalRatio;//最后被偷取的比例,比如被偷取用户损失了10个,最后偷取的用户获得这10个乘这个比例
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 68 - 7
src/main/java/com/td/boss/game/comusers/controller/ComUsersController.java

@@ -3,6 +3,13 @@ package com.td.boss.game.comusers.controller;
 import com.alibaba.fastjson.JSON;
 import com.td.boss.common.controller.*;
 import com.td.boss.common.pojo.Result;
+import com.td.boss.game.complayersattri.pojo.ComPlayersAttri;
+import com.td.boss.game.complayersattri.service.ComPlayersAttriService;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriSimpleVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
+import com.td.boss.game.comsetting.service.ComSettingService;
+import com.td.boss.game.comsetting.vo.ComSettingSimpleVo;
+import com.td.boss.game.comsetting.vo.ComSettingVo;
 import com.td.boss.game.comusers.vo.ComUsersSimpleVo;
 import com.td.boss.game.dappWs.DappWSServer;
 import com.td.boss.config.enums.ResultEnum;
@@ -39,8 +46,13 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
     private ComUsersService comUsersService;
 
     @Autowired
-    private JwtTokenUtil jwtTokenUtil;
+    private ComPlayersAttriService comPlayersAttriService;
+
+    @Autowired
+    private ComSettingService comSettingService;
 
+    @Autowired
+    private JwtTokenUtil jwtTokenUtil;
 
 
     @Value("${spring.profiles.active}")
@@ -173,7 +185,7 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
         String DAppOnlineUrl = "https://yt.landownership.live/api/account/loginValidate";
         String DAppTestUrl = "https://wp.landownership.live/api/account/loginValidate";
 
-        String DAppUrl = active.equals("prod")?DAppOnlineUrl:DAppTestUrl;
+        String DAppUrl = active.equals("prod") ? DAppOnlineUrl : DAppTestUrl;
         log.info("DApp登录地址:" + DAppUrl);
         RestTemplate restTemplate = new RestTemplate();
         HttpHeaders headers = new HttpHeaders();
@@ -205,14 +217,14 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
                 comUsersVo.setLastLogin(new Date());
                 comUsersVo.setCreateTime(new Date());
                 comUsersService.save(comUsersVo);
-            }else{
+            } else {
                 //如果是黑名单限制登录的用户,限制登录
-                if(comUsersVo.getLimitLogin().equals(1)){
+                if (comUsersVo.getLimitLogin().equals(1)) {
                     map.put("msg", "当前用户限制登录,请联系游戏管理人员!");
-                    return Result.of(map,false,ResultEnum.USER_LIMIT_LOGIN.getMessage(),ResultEnum.USER_LIMIT_LOGIN.getCode());
+                    return Result.of(map, false, ResultEnum.USER_LIMIT_LOGIN.getMessage(), ResultEnum.USER_LIMIT_LOGIN.getCode());
                 }
                 //记录一下用户的Address
-                if(comUsersVo.getAddress() == null){
+                if (comUsersVo.getAddress() == null) {
                     comUsersVo.setAddress(address);
                 }
                 //维护一个最后登录时间
@@ -224,6 +236,54 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
             map.put("token", token);
             map.put("active", active);
             map.put("userInfo", CopyUtil.copy(comUsersVo, ComUsersSimpleVo.class));
+
+            //获取一下用户属性,新增表
+            ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(comUsersVo.getUserId());
+            if (playersAttribute == null) {
+                // todo player 如果角色不存在的话,直接创建一个。
+                playersAttribute = new ComPlayersAttriVo();
+                playersAttribute.setUserId(comUsersVo.getUserId());
+                playersAttribute.setStrength(0);
+                playersAttribute.setLucky(0);
+                playersAttribute.setResetStrength(DateUtil.getNowDate());
+                playersAttribute.setCreateTime(DateUtil.getNowDate());
+                playersAttribute.setUpdateTime(DateUtil.getNowDate());
+                comPlayersAttriService.save(playersAttribute);
+            }else{
+                //todo 判断是否过了一天,是的话重置体力值
+                if(playersAttribute.getResetStrength() == null){
+                    playersAttribute.setStrength(0);
+                    playersAttribute.setResetStrength(DateUtil.getNowDate());
+                    comPlayersAttriService.save(playersAttribute);
+                }else{
+                    Long  _attributeTime =  DateUtil.getOldDateAddDay(playersAttribute.getResetStrength(),1).getTime()- DateUtil.getNowDate().getTime();
+                    if(_attributeTime<=0){
+                        playersAttribute.setStrength(0);
+                        playersAttribute.setResetStrength(DateUtil.getNowDate());
+                        comPlayersAttriService.save(playersAttribute);
+                    }
+                }
+
+            }
+            //获取一个配置
+            ComSettingVo comSettingVo = comSettingService.get("1").getData();
+            if (comSettingVo.equals(null)) {
+                return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
+            }
+            ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
+            //todo 后台可配置,获取一个链上数据
+            Integer _configStrength = comSettingVo.getMaxStrength() , _chainStrength = 0;
+            //前端的显示,输出一个不小于0的体力值
+            Integer _out = _configStrength - Math.abs(playersAttribute.getStrength());
+            comPlayersAttriSimpleVo.setCurrentStrength(_out < 0 ? 0 : _out);
+            //最大值是配置的值和链上数据的值相加
+            comPlayersAttriSimpleVo.setMaxStrength(_configStrength + _chainStrength);
+
+            //返回前端的体力值是读取一个配置的体力值,
+            map.put("playerAttribute", comPlayersAttriSimpleVo);
+
+            //返回一个游戏配置
+            map.put("gameSetting",CopyUtil.copy(comSettingVo, ComSettingSimpleVo.class));
             map.put("response", JSON.parse(response));
             return Result.of(map);
         } catch (HttpClientErrorException e) {
@@ -232,7 +292,7 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
             response = e.toString();
             map.put("active", active);
             map.put("response", response);
-            return Result.of(map,false,ResultEnum.USER_VERIFICATION_ERROR.getMessage(),ResultEnum.USER_VERIFICATION_ERROR.getCode());
+            return Result.of(map, false, ResultEnum.USER_VERIFICATION_ERROR.getMessage(), ResultEnum.USER_VERIFICATION_ERROR.getCode());
 
         }
 
@@ -261,6 +321,7 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
 
     /**
      * 获取用户的snb
+     *
      * @param userId
      * @return
      */

+ 6 - 6
src/main/java/com/td/boss/util/CodeDOM.java

@@ -532,11 +532,11 @@ public class CodeDOM {
        // String[] tables = {"sys_user","sys_menu","sys_authority","sys_user_menu","sys_user_authority","sys_shortcut_menu","sys_setting"};
        // String[] tables = {"com_player_goods","com_players","com_users","com_rewards"};
        // String[] tables = {"com_wallet","com_cnt_order","com_mall_seed","com_player_goods","com_player_land","com_config_land","com_fruit","com_snb_tran"};
-       // "com_player_log"
-        String[] tables = {"com_explain_land"};
-        for (String table : tables) {
-            String msg = new CodeDOM(table).create();
-            System.out.println(msg);
-        }
+       // "com_player_log" ,"com_explain_land","com_player_profit","com_players_attri"
+       // String[] tables = {"com_setting"};
+       // for (String table : tables) {
+       //     String msg = new CodeDOM(table).create();
+       //     System.out.println(msg);
+       // }
     }
 }

+ 10 - 0
src/main/java/com/td/boss/util/DateUtil.java

@@ -105,6 +105,16 @@ public class DateUtil {
         return cal.getTime();
     }
 
+    /**
+     * 获取输入时间 + N个天
+     */
+    public static Date getOldDateAddDay(Date date,Integer n){
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.DAY_OF_YEAR,+ n);
+        return cal.getTime();
+    }
+
     /**
      * 判断该日期是否是周一
      */

+ 123 - 0
src/main/java/com/td/boss/util/DoubleUtil.java

@@ -0,0 +1,123 @@
+package com.td.boss.util;
+
+/**
+ * @author:slambb
+ * @date:2022/2/18
+ */
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型
+ * 整型地方法适合于货币精度已知的情况,比如12.11+1.10转成1211+110计算,最后再/100即可
+ * 以下是摘抄的BigDecimal方法:
+ */
+public class DoubleUtil implements Serializable {
+    private static final long serialVersionUID = -3345205828566485102L;
+    // 默认除法运算精度
+    private static final Integer DEF_DIV_SCALE = 2;
+    /**
+     * 提供精确的加法运算。
+     *
+     * @param value1 被加数
+     * @param value2 加数
+     * @return 两个参数的和
+     */
+    public static Double add(Double value1, Double value2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(value1));
+        BigDecimal b2 = new BigDecimal(Double.toString(value2));
+        return b1.add(b2).doubleValue();
+    }
+    /**
+     * 提供精确的减法运算。
+     *
+     * @param value1 被减数
+     * @param value2 减数
+     * @return 两个参数的差
+     */
+    public static double sub(Double value1, Double value2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(value1));
+        BigDecimal b2 = new BigDecimal(Double.toString(value2));
+        return b1.subtract(b2).doubleValue();
+    }
+    /**
+     * 提供精确的乘法运算。
+     *
+     * @param value1 被乘数
+     * @param value2 乘数
+     * @return 两个参数的积
+     */
+    public static Double mul(Double value1, Double value2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(value1));
+        BigDecimal b2 = new BigDecimal(Double.toString(value2));
+        return b1.multiply(b2).doubleValue();
+    }
+    /**
+     * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。
+     *
+     * @param dividend 被除数
+     * @param divisor 除数
+     * @return 两个参数的商
+     */
+    public static Double divide(Double dividend, Double divisor) {
+        return divide(dividend, divisor, DEF_DIV_SCALE);
+    }
+    /**
+     * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。
+     *
+     * @param dividend 被除数
+     * @param divisor 除数
+     * @param scale  表示表示需要精确到小数点以后几位。
+     * @return 两个参数的商
+     */
+    public static Double divide(Double dividend, Double divisor, Integer scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException("The scale must be a positive integer or zero");
+        }
+        BigDecimal b1 = new BigDecimal(Double.toString(dividend));
+        BigDecimal b2 = new BigDecimal(Double.toString(divisor));
+        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+    /**
+     * 提供指定数值的(精确)小数位四舍五入处理。
+     *
+     * @param value 需要四舍五入的数字
+     * @param scale 小数点后保留几位
+     * @return 四舍五入后的结果
+     */
+    public static double round(double value,int scale){
+        if(scale<0){
+            throw new IllegalArgumentException("The scale must be a positive integer or zero");
+        }
+        BigDecimal b = new BigDecimal(Double.toString(value));
+        BigDecimal one = new BigDecimal("1");
+        return b.divide(one,scale, RoundingMode.HALF_UP).doubleValue();
+    }
+
+
+    /**
+     * 提供精确的判断大小。
+     *
+     * @param value1
+     * @param value2
+     * @return 两个参数比较大小
+     */
+    public static Integer compare(Double value1, Double value2) {
+        BigDecimal b1 = new BigDecimal(Double.toString(value1));
+        BigDecimal b2 = new BigDecimal(Double.toString(value2));
+
+        Integer result = 0;
+        if (b1.compareTo(b2) == 0) {
+            result = 0;
+        }else if (b1.compareTo(b2) < 0){
+            result = -1;
+        }else if (b1.compareTo(b2) > 0) {
+            result = 1;
+        }else{
+            throw new IllegalArgumentException("The compare is error!");
+        }
+        return result;
+    }
+}

+ 61 - 0
src/main/java/com/td/boss/util/RedisLock.java

@@ -0,0 +1,61 @@
+package com.td.boss.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author:slambb
+ * @date:2022/02/09
+ */
+@Component
+@Slf4j
+public class RedisLock {
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    /**
+     * 加锁
+     * @param key
+     * @param value 当前时间+超时时间
+     * @return
+     */
+    public boolean lock(String key, String value) {
+        if(redisTemplate.opsForValue().setIfAbsent(key, value)) {
+            return true;
+        }
+        //currentValue=A   这两个线程的value都是B  其中一个线程拿到锁
+        String currentValue = redisTemplate.opsForValue().get(key);
+        //如果锁过期
+        if (!StringUtils.isEmpty(currentValue)
+                && Long.parseLong(currentValue) < System.currentTimeMillis()) {
+            //获取上一个锁的时间
+            String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
+            if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 解锁
+     * @param key
+     * @param value
+     */
+    public void unlock(String key, String value) {
+        try {
+            String currentValue = redisTemplate.opsForValue().get(key);
+            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
+                redisTemplate.opsForValue().getOperations().delete(key);
+            }
+        }catch (Exception e) {
+            log.error("【redis分布式锁】解锁异常, {}", e);
+        }
+    }
+
+}

+ 36 - 0
src/main/resources/application.yml

@@ -60,6 +60,16 @@ spring:
       max-lifetime: 120000
       connection-timeout: 30000
       connection-test-query: SELECT 1
+
+  redis:
+    host: 42.192.165.168
+    port: 6379
+    password: abc123456abc-test
+    data: #工程中只是把redis作为缓存,并未使用redis作为数据持久化存储源repository使用.
+      redis:
+        repositories:
+          enabled: false
+
 #是否需要输入验证码
 captcha:
   enable: false
@@ -83,6 +93,22 @@ spring:
       max-lifetime: 120000
       connection-timeout: 30000
       connection-test-query: SELECT 1
+
+  redis:
+    host: 42.192.165.168
+    port: 6379
+#    lettuce: # 这里标明使用lettuce配置
+#      pool:
+#        max-active: 8   #连接池最大连接数(使用负值表示没有限制)
+#        max-wait: -1ms  #连接池最大阻塞等待时间(使用负值表示没有限制)
+#        max-idle: 8     #连接池中的最大空闲连接
+#        min-idle: 0     #连接池中的最小空闲连接
+#      timeout: 10000ms    #连接超时时间(毫秒)
+    password: abc123456abc-test
+  data: #工程中只是把redis作为缓存,并未使用redis作为数据持久化存储源repository使用.
+    redis:
+      repositories:
+        enabled: false
 #是否需要输入验证码
 captcha:
   enable: true
@@ -106,6 +132,16 @@ spring:
       max-lifetime: 120000
       connection-timeout: 30000
       connection-test-query: SELECT 1
+
+  redis:
+    host: 42.192.165.168
+    port: 6379
+    password: abc123456abc-test
+  data: #工程中只是把redis作为缓存,并未使用redis作为数据持久化存储源repository使用.
+    redis:
+      repositories:
+        enabled: false
+
 #是否需要输入验证码
 captcha:
   enable: true